Is there a short way to extract exactly one element from a `Vec`?

Viewed 676

I have a reference to a Vec and I want to extract a reference to exactly one element from it, and panic if there are any more elements or zero. The equivalent if I had an array would be:

let [x] = list;

but Vecs are dynamically sized, so that won't work here. I can think of one way to do it with a reference to a Vec, and a couple more that require ownership, but I'm wondering if there's a shorter and simpler way.

Unowned Option 1: Use assert! and indexing

assert_eq!(list.len(), 1);
let x = &list[0];

Owned Option 1: Use try_into()

let [x]: [i32; 1] = list.try_into().unwrap();

Owned Option 2: Use assert! and pop

assert_eq!(list.len(), 1);
let x = list.pop();

So, is there a shorter and clearer way?

1 Answers

You can use a slice pattern (playground):

let v = vec![1u32];
let x = match v.as_slice() {
    &[x] => x,
    _ => panic!("expected single element"),
};
// ... use x ...

It's not necessarily shorter, but it's clear, doesn't require ownership or mutation, and can be nicely generalized to more than one element to extract.

If instead of panicking you want to check the element count and extract x if it's the only element, you can use if let:

if let &[x] = v.as_slice() {
   // ... use x ...
}
Related