次のような配列があるとしましょう。
['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']
配列の長さや「x」がいつ発生するかはわかりません。「x」に到達したら、次の要素に到達するまで、次の要素を新しい配列にプッシュしますincludes?('x')
。
望ましい出力は次のようになります。
[['cat', 'dog']['dolphin','cougar', 'whale']]
どうすればこれを達成できますか?
次のような配列があるとしましょう。
['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']
配列の長さや「x」がいつ発生するかはわかりません。「x」に到達したら、次の要素に到達するまで、次の要素を新しい配列にプッシュしますincludes?('x')
。
望ましい出力は次のようになります。
[['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"]]