Reputation: 175
I have the following array:
arr = [0, 1, 1, 2, 3, 1, 0, 0, 1]
Without changing the order of the values, I need to subdivide arr
into smaller arrays at every occurrence of 0
, such that the result would be:
arr = [ [0, 1, 1, 2, 3, 1], [0], [0, 1] ]
If arr
were a string, I could use .split("0")
and then prepend the delimiter to each subarray. What would be the most efficient equivalent to .split()
in plain Ruby for arrays?
Upvotes: 4
Views: 432
Reputation: 80041
Since ActiveSupport defines an Array#split method in Ruby, we can use it as a starting point:
class Array
def split(value = nil)
arr = dup
result = []
if block_given?
while (idx = arr.index { |i| yield i })
result << arr.shift(idx)
arr.shift
end
else
while (idx = arr.index(value))
result << arr.shift(idx)
arr.shift
end
end
result << arr
end
end
# then, using the above to achieve your goal:
arr = [0, 1, 1, 2, 3, 1, 0, 0, 1]
arr.split(0).map { |sub| sub.unshift(0) }
# => [[0], [0, 1, 1, 2, 3, 1], [0], [0, 1]]
Note that your verbal phrasing of the algorithm (split and prepend) is what is happening here, but your expected output is different (there's an additional zero because of the way split
works).
Do you want to split before each zero? For this you could use slice_before
.
Do you want to split but drop empty arrays? This could be done with a quick compact
before prepending, but you would lose the [0]
subarray.
Do you want to split but drop the first element if empty?
Do you want to split on /0+/
?
Upvotes: 0
Reputation: 106027
Enumerable#slice_before
does this exact thing:
arr = [0, 1, 1, 2, 3, 1, 0, 0, 1]
p arr.slice_before(0).to_a
# => [[0, 1, 1, 2, 3, 1], [0], [0, 1]]
See it on repl.it: https://repl.it/FBhg
Upvotes: 4