Last active
November 22, 2020 23:39
-
-
Save patshaughnessy/3252e2e718445d991499e5cd08e1949c to your computer and use it in GitHub Desktop.
Rust Vec<String> find example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| fn main() { | |
| let needle = "list".to_string(); | |
| let haystack = ["some".to_string(), "long".to_string(), "list".to_string(), "of".to_string(), "strings".to_string()].to_vec(); | |
| if let Some(str) = haystack.iter().find(|&s| *s == needle) { | |
| println!("{}", needle); | |
| } else { | |
| println!("Nothing there..."); | |
| } | |
| } |
contains is definitely the idiomatic approach. Also, you can avoid repeating .to_string(), and you can rely more on type inference:
fn main() {
let needle = "list".into();
let haystack: Vec<_> = vec!["some", "long", "list", "of", "strings"]
.into_iter()
.map(String::from)
.collect();
if haystack.contains(&needle) {
println!("{}", needle);
} else {
println!("not found");
}
}And if you're going to do membership tests often, consider a set rather than a vector.
Author
Thanks all of you for the ideas!
Yup as I learned on StackOverflow, using contains seems a lot simpler and cleaner in this example. Using into_iter will also work, but isn't what I need in my app because I don't want to move the data out.
And thanks for the type inference tip - yes much cleaner.
The deeper issue for me is that Rust's & and && syntax can be very confusing, especially with iterators and closures. Will just take some getting used to I suppose :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In my search for an answer I found your Stack Overflow question, which seems to already have a pretty good answer.
A key line is "In your case
.iter()iterates over Strings by reference, so it gives&Stringelements. Then.find()gives you access to each iterated the element by reference again, so you end up with a&&Stringargument." This is why you've got that|&s| *s ==mess in your version — I agree that that syntax is confusing!I'm still learning Rust, and coming from Ruby things like
Stringvs&strand references in general still confuse me. But here's how I'd go about this.I was able to avoid that weird syntax by using
contains. Not sure if it's any more or less idiomatic of Rust (I'm still learning), but it seems tolerable?EDIT: Though as this tweet points out,
into_iterhelps simplify your original version a bit:(I'd avoid naming a variable
strcuz that's just confusing.)