I have an array, and I want to perform a delete_if on a subset (any n items) of that array (and it modifies the array in memory)
With the full array I can do
array.delete_if do |item|
should_be_deleted?(item)
end
If I want to restrict to the first n items, the following won't work
array.take(n).delete_if do |item|
should_be_deleted?(item)
end
As it will create a new array and perform the delete_if on that new array
Is there an alternative, like a take_and_delete_if that would delete only the first n items (if the block returns true for each) ?
EDIT :
I want to process from array a and b, c by chunks of 3 (and delete from the array after performing the operation)
by_batch_of(3, until: (proc { a.empty? })) do
# This sets an instance variable @by = 3, and will iterate as long as `a` has any item
process_from_a # Will move @by items in a to either array b or c or fail
process_from_b # Will move @by items in b to c or fail
process_from_c # Should move items or fail and put back in a
end
Sample processing method
process_from_a(by: @by)
a.take_and_delete_if(by: by) do |item| # The +take_and_delete_if+ methods is the one I need
b << item if reason1
c << item if reason2
reason1 or reason2 # Delete if the item was moved away
end
Performance is what I am looking for
Example
a = [1,2,3,4,5,6,7,8,9]
b = []
c = []
1st batch of 3
process_from_a(by: 3)
a = [3,4,5,6,7,8,9] # 3 failed so delete_if returned false, it remains in the array (order doesn't matter) b = [1] # 1 moved to b c = [2] # 2 moved to cprocess_from_b
a = [3,4,5,6,7,8,9] b = [] c = [1,2] # 2 moved to cprocess_from_c
a = [3,4,5,6,7,8,9,1] # 1 was rejected in a b = [] c = [] # 1,2 processed from c
The next iteration would for example process [3,4,5] from a, etc.
Performance
Suppose my array is very big (10k, 100k) and I want process items by batch of 10. I don't want expensive solutions to filter the first 10 items and delete_if the whole array with index < 10...