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 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.
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&String
elements. Then.find()
gives you access to each iterated the element by reference again, so you end up with a&&String
argument." 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
String
vs&str
and 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_iter
helps simplify your original version a bit:(I'd avoid naming a variable
str
cuz that's just confusing.)