有数组 [2,1,4,3]
, 希望得到 [ "2", "2/1", "2/1/4", "2/1/4/3"]
实现了个版本,觉得不够优雅。
[1,2,3,4].each_with_object([]) {|i, x| x << [x.last, i].compact.join('/') }
# =>
[ "1", "1/2", "1/2/3", "1/2/3/4"]
有更好的实现方法么~
[1,2,3,4].map {|i| (1..i).to_a.join("/")}
caicai,我这个怎么样。
[2, 1, 4, 3].map.with_index {|i,index| a[0,index+1].join("/")}
应该是这样 [2, 1, 4, 3].map.with_index {|i,index| a[0,index+1].join("/")}
[1,2,3,4].inject {|i, x| [i, x].join('/').tap { |i| puts i } }
1/2
1/2/3
1/2/3/4
=> "1/2/3/4"
我第一想到的是 inject,但是我没有好的思路输出成数组。
先 -1 再 +1 何必呢
(1..a.size).map { |index| a[0,index].join("/") }
# 我再来一个变种
a.map.with_index(1) { |_, i| a.first(i).join('/') }
真要为了优雅不计成本了呀?!
本来一次循环搞定的事要不要这么费劲?
str_arr = []
str = ''
arr.each {|e| str == '' ? str = "#{e}" : str = "#{str}/#{e}"; str_arr << str }
我觉得成本要综合来看, 有读代码成本(是否优雅); 内存成本(如变量的数量); CPU 成本(如迭代次数); 最终做个权衡。
只贴代码不说话,怕被打 ^_^
# 两行版
arr = [1, 2, 3, 4]
# 通俗易懂版
0.upto(arr.size - 1).collect { |len| arr[0..len].join('/') }
# => ["1", "1/2", "1/2/3", "1/2/3/4"]
# 需自行看Array#new代码版
Array.new(arr.size) { |len| arr[0..len].join('/') }
# => ["1", "1/2", "1/2/3", "1/2/3/4"]
# 单行版, 仅限ruby 2.5.0以上
[1, 2, 3, 4].yield_self { |arr| Array.new(arr.size) { |len| arr[0..len].join('/') } }
# => ["1", "1/2", "1/2/3", "1/2/3/4"]
rubocop 其实是不建议用 x.times.map / x.times.collect 这种用法的,可以看这里:
https://github.com/bbatsov/rubocop/blob/master/lib/rubocop/cop/performance/times_map.rb
会有这样的提示出现: Use Array.new with a block instead of .times.collect.
写 0.upto(arr.size - 1) 纯粹是为了容易看懂,一般情况下,都是用 Array.new(arr.size)
只说了结论,没有说原因,看上去也就是省掉了一个 Enumerator 的初始化,我不觉得是什么严重的性能问题。
而且写代码本来可读性就是很重要的,我觉得 x.times.map 读起来比 Array.new(x) 更直观一些。