12

I have a HashMap and need to get the first element:

type VarIdx = std::collections::HashMap<u16, u8>; fn get_first_elem(idx: VarIdx) -> u16 { let it = idx.iter(); let ret = match it.next() { Some(x) => x, None => -1, }; ret } fn main() {} 

but the code doesn't compile:

error[E0308]: match arms have incompatible types --> src/main.rs:5:15 | 5 | let ret = match it.next() { | _______________^ 6 | | Some(x) => x, 7 | | None => -1, 8 | | }; | |_____^ expected tuple, found integral variable | = note: expected type `(&u16, &u8)` found type `{integer}` note: match arm with an incompatible type --> src/main.rs:7:17 | 7 | None => -1, | ^^ 

how can I fix it?

1
  • 4
    I'd strongly encourage you to read the documentation of any method you are calling, especially when you get an error. For example, HashMap::iter has a tiny amount of documentation that explains all of your problems: "An iterator visiting all key-value pairs in arbitrary order. The iterator element type is (&'a K, &'a V)." Commented Jul 19, 2017 at 15:19

2 Answers 2

20

There is no such thing as the "first" item in a HashMap. There are no guarantees about the order in which the values are stored nor the order in which you will iterate over them.

If order is important then perhaps you can switch to a BTreeMap, which preserves order based on the keys.

If you just need to get the first value that you come across, in other words any value, you can do something similar to your original code: create an iterator, just taking the first value:

fn get_first_elem(idx: VarIdx) -> i16 { match idx.values().next() { Some(&x) => x as i16, None => -1, } } 

The method values() creates an iterator over just the values. The reason for your error is that iter() will create an iterator over pairs of keys and values which is why you got the error "expected tuple".

To make it compile, I had to change a couple of other things: -1 is not a valid u16 value so that had to become i16, and your values are u8 so had to be cast to i16.

As another general commentary, returning -1 to indicate failure is not very "Rusty". This is what Option is for and, given that next() already returns an Option, this is very easy to accomplish:

fn get_first_elem(idx: VarIdx) -> Option<u8> { idx.values().copied().next() } 

The .copied() is needed in order to convert the &u8 values of the iterator into u8.

Sign up to request clarification or add additional context in comments.

Comments

7

HashMap::iter returns an iterator over (&Key, &Value) pairs. What you want is HashMap::values, which produces an iterator that only produces the values of the HashMap.

Note that the order of the values is random. It has nothing to do with the order you put the values in or with the actual value of the values.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.