Reputation: 1379
I'm searching a method for converting:
[1,2,3,nil,4,5,nil,6,7,8,9]
into:
[[1,2,3],[4,5],[6,7,8,9]]
Is there a built-in way to do that in Ruby?
Upvotes: 0
Views: 315
Reputation: 8548
I would join the array and then split the array.
a =[1,2,3,nil,4,5,nil,6,7,8,9]
a = a.join("-").split("--")
a.map! { |a| a.split("-") }
a.map! {|e| e.map! {|f| f.to_i}}
puts a.inspect
#[[1, 2, 3], [4, 5], [6, 7, 8, 9]]
Made edits (based on comments), to make it an integer once again. Still not a good answer though.
Upvotes: 0
Reputation: 58234
I found kind of an interesting one. There's probably a way to shorten it:
[1,2,3,nil,4,5,nil,6,7,8,9].chunk {|e| e.nil?}.select {|e| not e[0]}.flatten(1).delete_if {|e| not e}
Upvotes: 1
Reputation: 160551
I'd use:
[1,2,3,nil,4,5,nil,6,7,8,9].slice_before{ |e| e.nil? }.map(&:compact)
=> [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
slice_before
is really powerful when you want to break an array into chunks, either by searching for a repeating pattern by passing in a regex, or something you can compute via the block. It's much too powerful to summarize right here so take time to read the documentation and play with the examples.
Upvotes: 6
Reputation: 3999
This should work:
array = [1,2,3,nil,4,5,nil,6,7,8,9]
array.inject([[]]) do |result, number|
number ? result.last << number : result << []
result
end
#=> [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
Explanation time :-)
-- EDIT --
Checking David's reply I checked Rails implementation of this:
def split(value = nil)
using_block = block_given?
inject([[]]) do |results, element|
if (using_block && yield(element)) || (value == element)
results << []
else
results.last << element
end
results
end
end
If you skip the block implementation, it has the exact same structure of my code. Yay! :)
Upvotes: 4