4 ms·
`..into a new array` is precisely what `reject` does. We're talking about `reject!` which modifies the existing array.
by phamilton 10y ago
`..into a new array` is precisely what `reject` does. We're talking about `reject!` which modifies the existing array.
- brandonbloom 10y agoxg15's comment still makes sense if you replace "copy all ..." with "slide the remaining elements down by the number of removed elements" to match the mutative behavior. However, a bigger problem is concurrent modification: What happens if your reject! predicate has a side effect which modifies the array? Ideally you'd receive a "ConcurrentModificationException" or the like.
- leereeves 10y agoThat would still require O(n) space (to store the list of elements to keep or remove) so why not simply use the regular `reject` ?
- brandonbloom 10y agoBecause you're saving the O(N) time copy... iirc, Ruby's array doesn't expose the distinction between length and capacity, but internally it may decide to amortize the cost of such copies. For example, if reject only removes a small % of elements, it may choose not to shrink capacity.
- leereeves 10y agoYou're not saving the O(N) time copy, just replacing it with an O(N) slide. (That's assuming you copy at all, instead of simply updating the reference.)
- brandonbloom 10y agoI meant O(N) space, as you said "That would still require O(n) space" - but a slide does not require additional space.
- junke 10y agoNo, before sliding elements, you set a local variable "dirty" to true. You iterate over all elements and keep the ones that are not rejected by moving them at the end of the current max index. When you code finishes normally, dirty is set to false. You have an "ensure" block (finally) protecting the code which handles the cases where dirty is true (moving all the remaining elements after the current max). Then you truncate the array.
- DannyBee 10y agoIsn't the simple solution for doing it in place "swap reject element position with current end of array, decrement size of array?" What am i missing?
- rtpg 10y agomaybe there's a finalization step that's necessary to free up memory? This seems like the most straightforward solution though
- perfmode 10y agoWouldn't that change the order of elements?
- DannyBee 10y agoThe only guarantee i saw was that the output array did not contain the rejected elements. (and looking at the reference docs, that's all it says) It appears order is guaranteed to be maintained but it's not specified :)
- danfang 10y agoNo. [1,2,3].reject! { |x| x == 1 } would give you [3,2], rearranging the order of elements. It would work for sets.