2

我有一种情况,我想将初始化的数组nils分成空段和包含连续数字运行的段。

我发现高阶chunk函数 为Array这个问题提供了一个优雅的解决方案:

<< [nil,nil,1,2,nil,3].chunk { |e| !e.nil? }.each { |e| p e }

>> [false, [nil, nil]]
>> [true, [1, 2]]
>> [false, [nil]]
>> [true, [3]]

但是,假设我希望输出还包含每个块中原始数组的起始索引,即将上面的输出增加为:

>> [false, 0, [nil, nil]]
>> [true, 2, [1, 2]]
>> [false, 4, [nil]]
>> [true, 5, [3]]

是否有一种解决方案可以保留上述块片段的表现力?

提前致谢。

4

2 回答 2

5

一种功能模块化方法:索引输入数组块,并将其映射到所需的输出 O(n):

data = xs.each_with_index.chunk { |x, i| !x.nil? }.map do |match, pairs| 
  [match, pairs.first[1], pairs.map(&:first)] 
end
#=> [[false, 0, [nil, nil]], [true, 2, [1, 2]], [false, 4, [nil]], [true, 5, [3]]]
于 2013-01-31T19:36:15.893 回答
1

您可以chunk自己浏览并跟踪起始索引的输出。只需按每个块的长度递增它。这是我的快速尝试。

chunked = [nil,nil,1,2,nil,3].chunk { |e| !e.nil? }

_, chunks_with_embedded_index = chunked.each_with_object([0, []]) do |(k, chunk), memo|
  memo[1] << [k, memo[0], chunk]
  memo[0] += chunk.length
end

chunks_with_embedded_index.each {|c| p c }
# >> [false, 0, [nil, nil]]
# >> [true, 2, [1, 2]]
# >> [false, 4, [nil]]
# >> [true, 5, [3]]

您可以将最后一个索引的临时变量提取到一个完整的局部变量中,并且实现更简洁:

chunked = [nil,nil,1,2,nil,3].chunk { |e| !e.nil? }

last_index = 0
chunks_with_embedded_index = chunked.reduce([]) do |memo, (k, chunk)|
  memo << [k, last_index, chunk]
  last_index += chunk.length
  memo
end

chunks_with_embedded_index.each {|c| p c }
# >> [false, 0, [nil, nil]]
# >> [true, 2, [1, 2]]
# >> [false, 4, [nil]]
# >> [true, 5, [3]]
于 2013-01-31T19:35:31.463 回答