Given a list, how can I split it into N sub-lists? They don't have necessarily have to be of the equal size. For instance, given 9 elements and split it into N = 3 sub-lists => 3x3. Or into N = 4 sub-lists => 2, 2, 2 and 1.
How can I do that? Isn't there a function in Elixir library?
Enum.split
splits a list into 2 parts
update:
If I have 7 elements and I want to split them into 3 sub-lists, there should be created 3 sublists:
[[3 elements], [2 elements], [2 elements]]
Namely, I want to preserve all the elements
You could consider using Enum.chunk_every
to split the list into sublists of n amount elements each:
some_list = [1, 2, 3, 4, 5, 6]
Enum.chunk_every(some_list, 2)
[[1, 2], [3, 4], [5, 6]]
By calculating the total length of the list first:
total_length = length(some_list)
and dividing that number with the desired amount of parts giving you the length of each chunk:
desired_amount_of_sublists = 3
chunk_length = Integer.floor_div(total_length, desired_amount_of_sublists)
should allow you to arbitrarily chunk the list into as many parts you require:
Enum.chunk_every(some_list, chunk_length)
[[1, 2], [3, 4], [5, 6]]
In the case that you have a hard requirement to have each sublist be of exactly n elements, then you can pass in the option :discard
to discard the last sublist if it is less than n elements:
Enum.chunk_every([1,2,3,4,5,6,7], 2, 2, :discard)
[[1, 2], [3, 4], [5, 6]]
In the case that you have the hard requirement where you cannot discard any element and for instance you need the remainder elements to be incorporated with the first sublist, then you can do as follows:
Say that with the above you arrive at:
result_so_far = Enum.chunk_every([1,2,3,4,5,6,7], 2)
[[1, 2], [3, 4], [5, 6], [7]]
First reverse result_so_far
, and take the first sublist thereof, which would be [7]
, as follows:
[last_sublist | other_sublists] = Enum.reverse(result_so_far)
Then you check the length of last_sublist
. If it corresponds to chunk_length
, then you are fine, result_so_far
has the desired result.
In the case it is smaller than chunk_length
, you will need to incorporate its elements with the first sublist of result_so_far
, which you can do as follows:
[first_sublist | rest ] = Enum.reverse(other_sublists)
[Enum.concat(first_sublist, last_sublist) | rest]
should then render
[[1, 2, 7], [3, 4], [5, 6]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With