Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: extract_if method #47

Open
vikanezrimaya opened this issue Jun 1, 2023 · 2 comments
Open

Feature request: extract_if method #47

vikanezrimaya opened this issue Jun 1, 2023 · 2 comments

Comments

@vikanezrimaya
Copy link

This method should take an FnMut(T) -> bool predicate, and then iterate over items in the priority queue in sorted order, popping and returning those items for which the predicate returns true.

Inspired by Vec::drain_filter(), which is currently marked unstable.

Since it iterates over all elements of the queue, it would obviously be O(n) complexity.

Dropping the iterator object should stop the iteration and preserve the remaining elements of the queue.

An equivalent workaround would be popping all elements of the queue, pushing them back if they don't match the predicate ­— however, I feel like this is prone to being incorrectly implemented (one could accidentally end up in an infinite loop) and/or being inefficient in general (to not end up in a loop, one may push back the unmatched items after the fact — but then collecting those items somewhere, say, in a Vec, is a waste of memory, while creating a second queue to push items back and swapping between queues might not be ergonomic).

@garro95
Copy link
Owner

garro95 commented Jun 2, 2023

It makes sense to me to wait for the std API to be stabilized, to avoid the need for breaking changes in this lib or to have a divergent API with respect to the std.

Some comments on your assumptions though. For the elements to be returned in order, the algorithm needs to be O(n log(n)).
Moreover, being able to iterate in order and to skip elements (i.e. don't remove the elements from the queue) is more challenging than you are prospecting, because of the way the heap algorithm works.

In my opinion, also to be consistent with other iterators (like iter and iter_mut) also the drain_filter implementation should return the elements in arbitrary order.

To have a drain_filter iterator in sorted order, one could convert the priority queue into_sorted_vec, then drain_filter it and finally convert it back into a PriorityQueue.

The complexity of unsorted drain_filter is O(n), while converting the queue into a sorted Vec is O(n log(n)), drain filtering it is O(n) and getting a PriorityQueue back would be O(m log(m)), where m is the number of remaining elements. So the total operation would be O(n log(n)) with one additional allocation for the sorted Vec

@garro95 garro95 changed the title Feature request: drain_filter method Feature request: extract_if method Aug 9, 2024
@garro95
Copy link
Owner

garro95 commented Aug 9, 2024

drain_filter has been renamed to extract_if now, in Vec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants