Snarf
Snarf

Reputation: 2361

Slice array when element reached

Lets say I have an array like so: ['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']

I don't know the length of the array or when an 'x' will occur. When I reach 'x' I want to push the following elements into a new array until I reach the next element that includes?('x').

The desired output would be: [['cat', 'dog']['dolphin','cougar', 'whale']]

How can I achieve this?

Upvotes: 3

Views: 201

Answers (5)

JCLL
JCLL

Reputation: 5545

Since Ruby 2.0, a nice solution is slice_before method or since 2.2 slice_when method :

We however need to drop the first element 'x' for each array generated :

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"]]

Upvotes: 0

dbenhur
dbenhur

Reputation: 20408

Enumerable#slice_before makes this simple:

a = ['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']
a.slice_before(/\Ax\z/).map { |chunk| chunk.drop(1) }
=> [["cat", "dog"], ["dolphin", "cougar", "whale"]]

Upvotes: 7

Aaron K
Aaron K

Reputation: 6961

Enumerable#chunk is the way to go. You can use nil to drop those chunks you don't want:

arr = ['x','cat', 'dog', 'x', 'dolphin', 'cougar', 'whale']

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

Upvotes: 3

maerics
maerics

Reputation: 156404

Good old Enumerable#reduce is handy for so many things:

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"]] 

[Edit] Also:

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

Upvotes: 2

steenslag
steenslag

Reputation: 80065

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"]]

Most of the work is chopping off the unneeded side results of the chunk method.

Upvotes: 3

Related Questions