A new function to pick elements from structures like vectors, arrays, etc

Proposal: Add a .pick(val) Method to Collection Types

Hello Rust community,

I'd like to propose (or at least start a conversation around) the addition of a .pick(val) method to standard collection types like Vec<T>, HashSet<T>, and HashMap<K, V>.

What .pick(val) Would Do

This method would search for a given value (or key), and:

  • Return it if found
  • Panic if not found

Example (on Vec<T>):

let nums = vec![1, 2, 3];
let x = nums.pick(2); // returns 2
let y = nums.pick(4); // panics: "Value not found in vector!"

This is conceptually similar to Option::expect(), but applied to containers.

Why This Might Be Useful

  • Improves ergonomics for common lookup patterns
  • Encourages clear “must-be-present” semantics
  • Reduces boilerplate like .iter().find(...).expect(...)
  • Aligns with similar patterns in other major languages (Python, JS, Ruby, etc.)

Candidate Data Structures

The .pick(val) method (or trait) could apply to:

  • Vec<T>
  • HashSet<T>
  • HashMap<K, V>
  • BTreeMap<K, V>
  • Possibly LinkedList<T>, IndexMap, etc.

Considerations

Of course, this should be used with care in production (like any panic-based function), and an idiomatic .try_pick(val) returning Option<T> might also be worth discussing.

Would love to hear thoughts from the community!

Thanks :folded_hands:

How is that different from indexing?

1 Like

it is ment to be a shorthand for

z.iter().find(|x| x == y).unwrap_or_else(|| panic!("{y} not found in {z}"))

not z[y]

1 Like

What is the purpose of returning a value you must already have? I can see one particular use for this operation, interning, but that is not a common operation, and when it is used, you need the “insert if not found” part too.

Can you explain this further and give examples of situations where this is desired? Of course, sometimes it makes sense to assert that a collection contains an element, but why do it exactly this way?

My understanding is that it is an intentional design decision that Vec/slices largely don’t contain methods that do linear searches; you have to write .iter() to make it clear that you are using a potentially costly linear operation.

Also, it’s not good practice to have a panicking search operation like this; panics should either

  • be performed in the calling code so that the panic message can be customized to the situation, or
  • be a consequence of a likely bug (e.g. out-of-bounds indexing).

Can you give examples of the same operation in Python and JS? I’m not aware of either one having a dedicated function for finding and returning the same value you put in.

9 Likes

Types that have heterogeneous PartialEq impl(s) would probably be the most common use case, but also types with a custom Eq that only compares a subset of the fields. That said, I agree that a method like this wouldn't be a good fit for Rust.

2 Likes

even then .pick(|x| x == y) would be much more flexible

for HashMap and BTreeMap, you can just use my_map[val].

Maybe instead of Vec::pick we could have a function like this?

impl<T: PartialEq> Vec<T> {
    /// Returns the number of items present in the `Vec` equivalent to `item`
    fn number_of(&self, item: T) -> usize {
        // snip
    }
}

Or maybe, for more flexibility:

impl<T> Vec<T> {
    fn number_of(&self, condition: fn(T) -> bool) -> usize {
        // snip
    }
}

Hardly seems worth it. v.number_of(p) can already be written v.into_iter().filter(p).count(), which is fine -- and more general since you can also use .iter() with a fn(&T) -> bool and such, rather than always consuming.

(Indeed, the Filter iterator type overrides the count method to do that efficiently, too.)