Skip to content

Add a take_any method #382

@timothee-haudebourg

Description

@timothee-haudebourg

It is not the first time I'm missing a method to remove an arbitrary element from a set or map. This issue has been solved in the standard library for BTreeSet and BTreeMap with the recent introduction of the pop_first and pop_last methods, but there is no equivalent for HashMap/HashSet.

What I'm looking for is as simple as that:

/// Removes an arbitrary element from the set.
fn take_any(&mut self) -> Option

It is currently impossible to remove an element from a HashMap/HashSet through remove or take without a preexisting reference to an element/key of the set/map. So to have such reference the only way is to clone one beforehand:

fn take_any<T: Clone>(set: &mut HashSet<T>) -> Option<T> {
  let result = set.iter().next()?.clone();
  set.remove(&result);
  result
}

It is possible without the Clone bound with the drain_filter that allows to drain the first item and keep the rest, but it seems expansive to me.

fn take_any<T>(set: &mut HashSet<T>) -> Option<T> {
  let mut taken = false;
  set.drain_filter(|_| {
    let take = !taken;
    taken = true;
    take
  }).next()
}

As for the name, it could also be named pop_any to reflect the pop_first and pop_last methods on BTreeSet and BTreeMap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions