了解在迭代器上调用方法两次时如何满足借用检查器?
Understanding how to satisfy borrow checker when calling method on iterator twice?
在下面的代码中,我了解到通过 zipped.filter
的调用已经完成了借用。我不明白的是如何修复它,如果我以后想再次使用 zipped
。
我是 Rust 的新手,所以如果在这段代码中有其他问题或奇怪的习语误用,我也对此很感兴趣,但主要是关于如何在这里使借用工作两次。
代码:
fn main() {
let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];
for s1 in &data {
for s2 in &data {
let zipped = s2.chars().zip(s1.chars());
// Did a diff of the two strings have only one character different?
if zipped.filter(|(a,b)| a != b).count() == 1 {
let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
println!("String without the different character: {}", newStr);
}
}
}
}
错误:
error[E0382]: use of moved value: `zipped`
--> a.rs:10:30
|
6 | let zipped = s2.chars().zip(s1.chars());
| ------ move occurs because `zipped` has type `Zip<Chars<'_>, Chars<'_>>`, which does not implement the `Copy` trait
...
9 | if zipped.filter(|(a,b)| a != b).count() == 1 {
| ---------------------- `zipped` moved due to this method call
10 | let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
| ^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `zipped`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
您始终可以 zipped.clone()
,它会克隆迭代器,以便您在首次调用 filter(...).count()
时移动克隆。原始 zipped
保持不变,您将把它移动到第二个 filter(...).collect()
.
请注意,它不会克隆任何数据,因为迭代器是惰性的,复制迭代器意味着复制其逻辑(因此它复制了 .chars()
、.zip()
等逻辑,这只是一堆函数指针,而不是数据)。
fn main() {
let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];
for s1 in &data {
for s2 in &data {
let zipped = s2.chars().zip(s1.chars());
// << THE CHANGE IS HERE
if zipped.clone().filter(|(a,b)| a != b).count() == 1 {
let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
println!("String without the different character: {}", newStr);
}
}
}
}
输出:
String without the different character: bc
String without the different character: bc
在下面的代码中,我了解到通过 zipped.filter
的调用已经完成了借用。我不明白的是如何修复它,如果我以后想再次使用 zipped
。
我是 Rust 的新手,所以如果在这段代码中有其他问题或奇怪的习语误用,我也对此很感兴趣,但主要是关于如何在这里使借用工作两次。
代码:
fn main() {
let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];
for s1 in &data {
for s2 in &data {
let zipped = s2.chars().zip(s1.chars());
// Did a diff of the two strings have only one character different?
if zipped.filter(|(a,b)| a != b).count() == 1 {
let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
println!("String without the different character: {}", newStr);
}
}
}
}
错误:
error[E0382]: use of moved value: `zipped`
--> a.rs:10:30
|
6 | let zipped = s2.chars().zip(s1.chars());
| ------ move occurs because `zipped` has type `Zip<Chars<'_>, Chars<'_>>`, which does not implement the `Copy` trait
...
9 | if zipped.filter(|(a,b)| a != b).count() == 1 {
| ---------------------- `zipped` moved due to this method call
10 | let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
| ^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `zipped`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
您始终可以 zipped.clone()
,它会克隆迭代器,以便您在首次调用 filter(...).count()
时移动克隆。原始 zipped
保持不变,您将把它移动到第二个 filter(...).collect()
.
请注意,它不会克隆任何数据,因为迭代器是惰性的,复制迭代器意味着复制其逻辑(因此它复制了 .chars()
、.zip()
等逻辑,这只是一堆函数指针,而不是数据)。
fn main() {
let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];
for s1 in &data {
for s2 in &data {
let zipped = s2.chars().zip(s1.chars());
// << THE CHANGE IS HERE
if zipped.clone().filter(|(a,b)| a != b).count() == 1 {
let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
println!("String without the different character: {}", newStr);
}
}
}
}
输出:
String without the different character: bc
String without the different character: bc