'Idiomatic Rust for Vec<Vec<String>> filter
Very new to programming and for some reason i chose rust to start with but i digress...
Current code to take a reference to a vec of vec strings, compare one 'Column' against some array and return the row and a truncated version of the row.
The below compiles, but i keep re-using this same logic across all my functions and would be really useful to just have some kind of closure.
fn niacs(vec:&Vec<Vec<String>>, naics: Vec<&str> ) -> (Vec<Vec<String>>,Vec<Vec<String>>) {
let mut return_vec_truncated = vec![];
let mut return_vec_full = vec![];
let mut contains_naice = false;
for i in vec.iter() {
for naic in naics.iter(){
if i[31] == *naic {
contains_naice = true;
}
if contains_naice {
let x = info_wanted(&i);
return_vec_truncated.push(x);
return_vec_full.push(i.clone());
}
contains_naice = false;
}
}
(return_vec_full, return_vec_truncated)
}
What i would like to be able to do is write something like:
let x = vec.iter().map(|x| x.iter()).filter(|x| x != naics);
The problem is.. I don't want to map across all of the elements per say, i just want to make across one column within the inner vec, which is column 31.
Sample Vec of Vec:
["471", "001020887", "", "1SNH0", "", "A", "Z2", "20020312", "20210711", "20200731", "20200731", "BENCHMARK INTERNATIONAL, INC", "", "", "", "5025 PIRATES COVE RD", "", "JACKSONVILLE", "FL", "32210", "8309", "USA", "04", "19990208", "1231", "http://www.bmiint.com", "2L", "VA", "USA", "0005", "27~2X~A5~QF~XS", "541611", "", "0002", "541611Y~541690Y", "0000", "", "N", "", "5025 PIRATES COVE RD", "", "JACKSONVILLE", "32210", "8309", "USA", "FL", "ANNA", "", "MCKENZIE", "", "5025 PIRATES COVE RD", "", "JACKSONVILLE", "32210", "8309", "USA", "FL", "4437170460", "", "", "", "[email protected]"], ["472", "001021310", "", "94867", "", "A", "Z2", "19980424", "20210323", "20200323", "20200323", "CHURCHILL CORPORATION", "", "", "", "344 FRANKLIN ST", "", "MELROSE", "MA", "02176", "1825", "USA", "05", "19480101", "0731", "", "2L", "MA", "USA", "0002", "2X~MF", "332322", "", "0001", "332322Y", "0000", "", "Y", "", "P.O.BOX 761038", "", "MELROSE", "02176", "1825", "USA", "MA", "MARSHALL", "W", "SCHERMERHORN", "", "P.O. BOX 761038", "344 FRANKLIN STREET", "MELROSE", "02176", "", "USA", "MA", "7816654700", "", "", "7816625291", "[email protected]"]]
Solution 1:[1]
First, to confirm that I'm not overlooking something:
Your code is equal to
fn niacs(vec: &Vec<Vec<String>>, naics: Vec<&str>) -> (Vec<Vec<String>>, Vec<Vec<String>>) {
let mut return_vec_truncated = vec![];
let mut return_vec_full = vec![];
for i in vec.iter() {
for naic in naics.iter() {
if i[31] == *naic {
return_vec_truncated.push(info_wanted(&i));
return_vec_full.push(i.clone());
}
}
}
(return_vec_full, return_vec_truncated)
}
and the contains_naice is unnecessary? Except for contains_naice, I think your code easy to read and plenty idiomatic.
If you absolutely want to write it with iterators, you can use flat_map and unzip:
fn niacs(vec: &Vec<Vec<String>>, naics: Vec<&str>) -> (Vec<Vec<String>>, Vec<Vec<String>>) {
vec.iter()
.flat_map(|i| naics.iter().filter(|naic| i[31] == **naic).map(move |_| i))
.map(|i| (i.clone(), info_wanted(&i)))
.unzip()
}
Though I do wonder: Is that actually what you wanted? Do you really want one copy of i per matching naic? Or do you maybe want one copy of i if any of the naics match?
fn niacs(vec: &Vec<Vec<String>>, naics: Vec<&str>) -> (Vec<Vec<String>>, Vec<Vec<String>>) {
vec.iter()
.filter(|i| naics.iter().any(|naic| i[31] == *naic))
.map(|i| (i.clone(), info_wanted(&i)))
.unzip()
}
(The equal iterative code would have a break inside the if.)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
