Access an element of a vector

Hi,
I'm learning about vectors and I have a question about this

 pub struct Employee {
        id: u32,
        name: String,
        mail: String,
    }

let employees = vec![
    Employee{
        id:1, 
        name:"Jhon".to_string(), 
        mail:"test1@domain.com".to_string()
    },
    Employee{
        id:2, 
        name:"Lucas".to_string(), 
        mail:"test2@domain.com".to_string()
    },
    Employee{
        id:2, 
        name:"Mery".to_string(), 
        mail:"test3@domain.com".to_string()
    }
    //n...
];

How do I access the element and get the property?

print!("{}",employees.get(0).name) //error

if i want to access the employee with id 3 or id 100, do i have to iterate the whole list?

get returns an Option since the vector could potentially not contain that element. If you know it's in the vector you can index it like employees[0].name. If you want to find an employee in the list with a given ID, you would have to iterate, which you can do like employees.iter().find(|&e| e.id == 3) (this also returns an Option, so you'll need to unwrap it or handle the case where it's missing.)

You should use indexing with the [] operator:

let employees = vec![
    Employee { /* ... */ }
];

let first_employee_name = employees[0].name.clone();

Instead of a java-style get method.

For accessing it based on a property, it's really up to how you want to store the data. If you want to pay the cost of having to sort it, you could sort it by id. You could also use a hashmap and use the key as id if it's unique. Or you could just iterate through the array and find it:

let employees = vec![ /* ... */ ];

let with_id_20 = employees
    .iter()
    .filter(|x| x.id == 20)
    .next();

match with_id_20 {
    Some(employee) => { /* We found one */ },
    None => { /* We didn't find one */ },
}

Additionally, if you want to fallibly acquire an index, and get an Option back, you can use the get method given by its deref into slice, or its get_mut method if you wish to modify it.

1 Like

You're right is better with HashMap

How can I return a value using match?

use std::collections::HashMap;

pub struct Employee {
    name: String,
    mail: String,
}

pub fn get_employee(id:u32) -> Employee{
    
    let mut employees = HashMap::new();
    employees.insert(1, Employee{name: "Jhon".to_string(), mail:"t1@domain.com".to_string()});
    employees.insert(2, Employee{name: "Mery".to_string(), mail:"t2@domain.com".to_string()});

    match employees.get(&id) {
        Some(employee) => employee,
        None => println!("No found"),
    }
}

fn main() {
    let jhon = get_employee(1);
    
}

error[E0308]: `match` arms have incompatible types
  --> src/main.rs:16:17
   |
14 | /     match employees.get(&id) {
15 | |         Some(employee) => employee,
   | |                           -------- this is found to be of type `&Employee`
16 | |         None => println!("No found"),
   | |                 ^^^^^^^^^^^^^^^^^^^^ expected `&Employee`, found `()`
17 | |     }
   | |_____- `match` arms have incompatible types
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

You ARE returning values already from the match. but all branches of the match must return the same kind of value. your Some is returning an Employee and None is printing something. They don't match.

You need to explain what you Actually want to happen. Do you want the program to crash if it's a None? or do you want to print then keep going? Of you want it to keep going what do you want 'jhon' to be after the function if it's a 'None'?

Also I don't see how the hashmap helps at all. A Vec is much more suitable here. Are you trying to ensure IDs are unique? In that case a HashMap is okay.