Warm tip: This article is reproduced from serverfault.com, please click

How to convert Vec<Item> to Vec<String>?

发布于 2020-12-04 19:34:39

I have the following object, and trying to convert Vec<Courses> and retrieve CourseName.

pub struct Schools {
    pub courses: Vec<CourseName>,
}

pub struct CourseName(String);

impl CourseName {
    pub fn as_str(&self) -> &str {
        &self.0[..]
    }
}

Trying to get the Vec<String>, but my following approach does not work,

assigned_courses:Vec<String> = courses.iter().map(|c| c.clone().as_str()).collect()

getting the following error:

value of type `Vec<std::string::String>` cannot be built from `std::iter::Iterator<Item=&str>`

Update:

enter image description here

Questioner
casillas
Viewed
0
vallentin 2020-12-05 04:14:45

The map closure receives a &CourseName so clone just copies the reference. What you instead want is to access the tuple and clone the inner String with c.0.

let assigned_courses: Vec<String> = courses.iter().map(|c| c.0.clone()).collect();

Alternatively, if references to the course names are enough, then instead you can use as_str on the inner String.

let assigned_courses: Vec<&str> = schools.courses.iter().map(|c| c.0.as_str()).collect();

To fix the "private field" error. You can add a visibility modifier, e.g.

pub struct CourseName(pub String);

However, it's probably better to keep it as private, and instead add a method like as_str().

impl CourseName {
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

Then resulting in:

let assigned_courses: Vec<String> = schools.courses.iter().map(|c| c.as_str().to_string()).collect();

Alternatively, you could also impl AsRef<str> and/or Display for CourseName, to make everything more generalized.


Assuming that CourseName is just to have a typed version instead of a String. Then you could instead impl Display for CourseName.

use std::fmt;

pub struct CourseName(String);

impl fmt::Display for CourseName {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

This allows you to do println!("{}, course") along with course.to_string().

let assigned_courses: Vec<String> = schools.courses.iter().map(|c| c.to_string()).collect();