到达元素时切片数组



假设我有一个这样的数组:['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']

我不知道数组的长度,也不知道"x"何时会出现。当我到达'x'时,我想将以下元素推入一个新数组,直到我到达includes?('x')的下一个元素。

期望的输出将是:[['cat', 'dog']['dolphin','cougar', 'whale']]

我怎样才能做到这一点?

Enumerable#slice_before让这个变得简单:

a = ['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']
a.slice_before(/Axz/).map { |chunk| chunk.drop(1) }
=> [["cat", "dog"], ["dolphin", "cougar", "whale"]]
ar =  ['x', 'cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']
p ar.chunk{|el| el == 'x'}.each_slice(2).map{|el| el.last.last}
#=> [["cat", "dog"], ["dolphin", "cougar", "whale"]]

大部分工作是砍掉chunk方法不需要的副作用。

Enumerable#chunk是可行的方法。你可以使用nil来删除那些你不想要的块:

arr = ['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']
arr.chunk{ |e| e != 'x' || nil }.map(&:last)
#=> [["cat", "dog"], ["dolphin", "cougar", "whale"]]

好旧的Enumerable#reduce是方便这么多的事情:

def split_array_by_item(array, item)
  array.reduce([]) do |memo, x|
    memo.push([]) if (x == item) || memo.empty?
    memo[-1].push(x) unless x == item
    memo
  end
end
a = ['x', 'cat', 'dog', 'x', 'dolphin', 'cougar', 'whale'] 
split_array_by_item(a, 'x') # => [["cat", "dog"], ["dolphin", "cougar", "whale"]] 

[编辑]

def split_array_by_item(array, item)
  array.chunk{|x|x==item}.reject(&:first).map(&:last)
end

自Ruby 2.0以来,一个很好的解决方案是slice_before方法或自2.2 slice_when方法:

然而,我们需要删除生成的每个数组的第一个元素x:

ary =  ['x', 'cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']
ary.slice_before{|e| e=='x'}.map{|t| t.drop(1)}
#==> [["cat", "dog"], ["dolphin", "cougar", "whale"]]
ary.slice_when{|i,j| j=='x'}.map{|t| t.drop(1)}
#==> [["cat", "dog"], ["dolphin", "cougar", "whale"]]

相关内容

  • 没有找到相关文章

最新更新