Being new to Ruby, I have a question about the difference between the .reject! and .delete_if methods when dealing with hashes and arrays. If just wanting to get rid of certain objects, is there functionally any difference between the methods? And reason to use one over the other?
Thanks!
EDIT I have read the documentation...I guess I should have been more clear in my original question. I was wondering more about differences in efficiency. Do they operate differently in how they delete items? (Again, ignoring return value. I understand that is a difference. Thanks!)
The reject() of enumerable is an inbuilt method in Ruby returns the items in the enumerable which does not satisfies the given condition in the block. It returns an enumerator if no block is given. Syntax: enu.reject { |obj| block } Parameters: The function takes a block whose condition is used to find the elements.
Ruby | Array delete_if() operation Array#delete_if() : delete_if() is a Array class method which deletes the arrays elements for which the block condition satisfies. Syntax: Array.delete_if() Parameter: block - condition for deleting the elements. Return: array after deleting the elements.
%w(foo bar) is a shortcut for ["foo", "bar"] . Meaning it's a notation to write an array of strings separated by spaces instead of commas and without quotes around them.
Ruby | Array delete() operation Array#delete() : delete() is a Array class method which returns the array after deleting the mentioned elements. It can also delete a particular element in the array. Syntax: Array. delete() Parameter: obj - specific element to delete Return: last deleted values from the array.
reject
- create a new array without elements that match and return the new arraydelete_if
- delete elements that match from current array and return the arrayreject!
- delete elements that match from current array. Return the array if something was rejected, or nil
when none.The documentation is pretty clear about this.
The difference is that if reject!
does not change the array, it returns nil
. delete_if
will return the unchanged array.
tl;dr: delete_if
seems slightly faster. However, the main consideration for choosing a method is the difference in the return value, as pointed out in the other answers.
Since you clarified that your question is concerning efficiency, I did a few tests:
> time { (1..100000).to_a.reject!{ |n| n % 5 == 0 } }
0.390000 0.000000 0.390000 ( 0.394596)
> time { (1..100000).to_a.delete_if{ |n| n % 5 == 0 } }
0.400000 0.000000 0.400000 ( 0.399122)
> time { (1..200000).to_a.reject!{ |n| n % 5 == 0 } }
1.650000 0.000000 1.650000 ( 1.657927)
> time { (1..200000).to_a.delete_if{ |n| n % 5 == 0 } }
1.630000 0.010000 1.640000 ( 1.637719)
> time { (1..300000).to_a.reject!{ |n| n % 5 == 0 } }
3.700000 0.000000 3.700000 ( 3.717206)
> time { (1..300000).to_a.delete_if{ |n| n % 5 == 0 } }
3.660000 0.000000 3.660000 ( 3.686213)
> time { (1..400000).to_a.reject!{ |n| n % 5 == 0 } }
7.320000 0.020000 7.340000 ( 7.361767)
> time { (1..400000).to_a.delete_if{ |n| n % 5 == 0 } }
7.190000 0.020000 7.210000 ( 7.239549)
So, looks like that beyond a certain size delete_if
is slightly faster.
time
is defined as:
def time(&block)
puts Benchmark.measure(&block)
end
The numbers represent user CPU time, system CPU time, the sum of the user and system CPU times, and the elapsed real time, respectively. You can find here an explanation of their meanings. Note that as in every benchmark, YMMV, and you should test on your specific workflows rather than my contrived example of removing numbers that are multiples of 5.
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