Suppose I have an array like this:
arr=[["1"], ["1"], ["2", "2"], ["2.1", "0.8"], ["2.2", "0.2"],
["1"], ["2", "3"], ["2", "0.8"], ["2", "0.4"], ["1"], ["2"],
["1", "0.8"], ["2", "0.4"], ["3", "0.3"]]
ie, a series of sublist (1 or more) of length 1 followed by a series of sublists (1 or more) of length greater than 1.
I want to divide that list into:
[[["1"], ["1"], ["2", "2"], ["2.1", "0.8"], ["2.2", "0.2"]],
[["1"], ["2", "3"], ["2", "0.8"], ["2", "0.4"]],
[["1"], ["2"], ["1", "0.8"], ["2", "0.4"], ["3", "0.3"]]]
ie, the sub lists of length 1 combined with the following sublists of length greater than 1 into a single sublist of those sublists.
This works:
data = []
while arr.length > 0
tmp = []
while arr.length > 0 && arr[0].length() == 1
tmp << arr.shift
end
while arr.length > 0 && arr[0].length() > 1
tmp << arr.shift
end
data << tmp
end
p data
# [[["1"], ["1"], ["2", "2"], ["2.1", "0.8"], ["2.2", "0.2"]], [["1"], ["2", "3"], ["2", "0.8"], ["2", "0.4"]], [["1"], ["2"], ["1", "0.8"], ["2", "0.4"], ["3", "0.3"]]]
But that seems super clumsy. Is there a .groupby
or flip/flop or some form of Ruby enumerator I am missing to do this more easily?
CodePudding user response:
As an improvement on @dawg's answer, if the block we pass to :slice_when
checks for the length of b
being greater than the length of a
:
data = arr.slice_when { |a, b| b.length < a.length }.to_a
Result is:
[[["1"], ["1"], ["2", "2"], ["2.1", "0.8"], ["2.2", "0.2"]],
[["1"], ["2", "3"], ["2", "0.8"], ["2", "0.4"]],
[["1"], ["2"], ["1", "0.8"], ["2", "0.4"], ["3", "0.3"]]]
To make this more robust, we can check that we're only doing this when b
has length 1
.
data = arr.slice_when { |a, b| b.length == 1 && b.length < a.length }.to_a
Now, if:
arr = [["1"], ["1"], ["2", "2"], ["2.1", "0.8"], ["2.2", "0.2"], ["1", "3", "4"], ["1", "1"],
["1"], ["2", "3"], ["2", "0.8"], ["2", "0.4"], ["1"], ["2"],
["1", "0.8"], ["2", "0.4"], ["3", "0.3"]]
The result is:
[[["1"], ["1"], ["2", "2"], ["2.1", "0.8"], ["2.2", "0.2"], ["1", "3", "4"], ["1", "1"]],
[["1"], ["2", "3"], ["2", "0.8"], ["2", "0.4"]],
[["1"], ["2"], ["1", "0.8"], ["2", "0.4"], ["3", "0.3"]]]