避免嵌套 for 循环中的重复项
Avoid duplicates in nested for loop
我在 Rust 中有以下嵌套 for 循环:
#[derive(Debug)]
struct Tes2 {
a: Vec<String>,
b: Vec<Vec<String>>,
}
fn vectes() {
let mut ff: Vec<Tes2> = Vec::new();
let one = vec![
vec!["a".to_string(), "b".to_string()],
vec!["x".to_string(), "y".to_string()],
];
let two = vec![
vec![
vec!["d".to_string(), "e".to_string()],
vec!["g".to_string(), "h".to_string()],
vec!["j".to_string(), "k".to_string()],
],
vec![
vec!["mm".to_string(), "nn".to_string()],
vec!["oo".to_string(), "pq".to_string()],
vec!["rr".to_string(), "ss".to_string()],
],
];
for i in one {
for (mut k, j) in two.clone().into_iter().enumerate() {
if k != 1 {
ff.push(Tes2 { a: i.clone(), b: j });
}
k += 1;
}
}
println!("{:?}", ff);
}
其输出为:
[Tes2 { a: ["a", "b"], b: [["d", "e"], ["g", "h"], ["j", "k"]] }, Tes2 { a: ["x", "y"], b: [["d", "e"], ["g", "h"], ["j", "k"]] }]
这就是我想要的,而且是正确的。本质上,在每个新结构中,我试图将 one[0]
与 two[0]
配对,然后将 one[1]
与 two[1]
配对,等等
我确信有一种更真实、更有效的“Rust 方式”可以做到这一点,也许使用 map 方法,并完全避免 for 循环,但我尝试过不同的方式,但从未奏效。
您要找的方法是Iterator::zip()
(or since Rust 1.59.0, std::iter::zip()
).
for (a, b) in std::iter::zip(one, two) {
ff.push(Tes2 { a, b })
}
到那个时候,你可以完全避免使用循环而只使用 collect()
:
let ff: Vec<_> = std::iter::zip(one, two)
.map(|(a, b)| Tes2 { a, b })
.collect();
当然,一个简单的循环总是可行的:
for i in 0..one.len() {
ff.push(Tes2 {
a: one[i].clone(),
b: two[i].clone(),
});
}
附带说明一下,使用 .iter().clone()
比 .clone().into_iter()
更好。参见 How to determine whether to use .clone() and .cloned() with iterators。
我在 Rust 中有以下嵌套 for 循环:
#[derive(Debug)]
struct Tes2 {
a: Vec<String>,
b: Vec<Vec<String>>,
}
fn vectes() {
let mut ff: Vec<Tes2> = Vec::new();
let one = vec![
vec!["a".to_string(), "b".to_string()],
vec!["x".to_string(), "y".to_string()],
];
let two = vec![
vec![
vec!["d".to_string(), "e".to_string()],
vec!["g".to_string(), "h".to_string()],
vec!["j".to_string(), "k".to_string()],
],
vec![
vec!["mm".to_string(), "nn".to_string()],
vec!["oo".to_string(), "pq".to_string()],
vec!["rr".to_string(), "ss".to_string()],
],
];
for i in one {
for (mut k, j) in two.clone().into_iter().enumerate() {
if k != 1 {
ff.push(Tes2 { a: i.clone(), b: j });
}
k += 1;
}
}
println!("{:?}", ff);
}
其输出为:
[Tes2 { a: ["a", "b"], b: [["d", "e"], ["g", "h"], ["j", "k"]] }, Tes2 { a: ["x", "y"], b: [["d", "e"], ["g", "h"], ["j", "k"]] }]
这就是我想要的,而且是正确的。本质上,在每个新结构中,我试图将 one[0]
与 two[0]
配对,然后将 one[1]
与 two[1]
配对,等等
我确信有一种更真实、更有效的“Rust 方式”可以做到这一点,也许使用 map 方法,并完全避免 for 循环,但我尝试过不同的方式,但从未奏效。
您要找的方法是Iterator::zip()
(or since Rust 1.59.0, std::iter::zip()
).
for (a, b) in std::iter::zip(one, two) {
ff.push(Tes2 { a, b })
}
到那个时候,你可以完全避免使用循环而只使用 collect()
:
let ff: Vec<_> = std::iter::zip(one, two)
.map(|(a, b)| Tes2 { a, b })
.collect();
当然,一个简单的循环总是可行的:
for i in 0..one.len() {
ff.push(Tes2 {
a: one[i].clone(),
b: two[i].clone(),
});
}
附带说明一下,使用 .iter().clone()
比 .clone().into_iter()
更好。参见 How to determine whether to use .clone() and .cloned() with iterators。