Passing Vec<String> as IntoIterator<&'a str>

和自甴很熟 提交于 2019-12-12 11:31:05

问题


I have a function that is supposed to pick random words from a list of words:

pub fn random_words<'a, I, R>(rng: &mut R, n: usize, words: I) -> Vec<&'a str>
where
    I: IntoIterator<Item = &'a str>,
    R: rand::Rng,
{
    rand::sample(rng, words.into_iter(), n)
}

Presumably that's a reasonable signature: Since I don't actually need the string itself in the function, working on references is more efficient than taking a full String.

How do I elegantly and efficiently pass a Vec<String> with words that my program reads from a file to this function? I got as far as this:

extern crate rand;

fn main() {
    let mut rng = rand::thread_rng();
    let wordlist: Vec<String> = vec!["a".to_string(), "b".to_string()];

    let words = random_words(&mut rng, 4, wordlist.iter().map(|s| s.as_ref()));
}

Is that the proper way? Can I write this without explicitly mapping over the list of words to get a reference?


回答1:


You can change your generic function to take anything that can be turned into a &str instead of having it take an iterator that yields a &str:

pub fn random_words<'a, I, R, J>(rng: &mut R, n: usize, words: I) -> Vec<&'a str>
where
    I: IntoIterator<Item = &'a J>,
    J: AsRef<str> + 'a,
    R: rand::Rng,
{
    rand::sample(rng, words.into_iter().map(AsRef::as_ref), n)
}
let words: Vec<&str> = random_words(&mut rng, 4, &wordlist);

The Book even has an entire chapter devoted to this topic



来源:https://stackoverflow.com/questions/35626122/passing-vecstring-as-intoiteratora-str

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!