E0597 试图循环一个向量
E0597 trying to loop over an vector
我正在通过一些编程练习自学 Rust。这里我有一个 Vec<String>
我从一个文件中读出,我试图将每行中的字母放在 HashSet
中,然后取所有行的交集。
当我这样做时,我收到一条错误消息,提示我的循环变量寿命不够长。
我直觉哪里出了问题——我有一个变量 l
,它的生命周期是循环的一次迭代,另一个变量 candidates 的生命周期是整个循环,第二个变量是从首先。但是我该如何解决这个问题?
let mut candidates = HashSet::<&u8>::new();
let mut sum = 0;
for l in lines { // lines is Vec<String>
if candidates.len()==0 {
candidates = HashSet::<&u8>::from_iter(l.as_bytes());
println!("candidates = {:?}", candidates);
} else if l.len() == 0 { // error message "borrow later used here"
// end of group
sum = sum + candidates.len();
candidates = HashSet::<&u8>::new();
} else {
let h2 = HashSet::<&u8>::from_iter(l.as_bytes()); // error message "borrowed value does not live long enough"
candidates = candidates.intersection(&h2).copied().collect();
println!("candidates = {:?}", candidates);
}
println!("{}", l);
}
我尝试复制 l
let mut l2:String = "".to_string();
for l in lines {
if candidates.len()==0 {
l2 = l.to_string();
candidates = HashSet::<&u8>::from_iter(l2.as_bytes());
但是我得到了一个不同的错误 error[E0506]: cannot assign to l2 because it is borrowed
。
as_bytes
将您的 l
字符串转换为字节切片。切片是对连续元素序列的引用。编译器指出在您的 for 循环结束时,引用无效。
一种解决方案是使用 &lines
:
迭代字符串引用
let mut candidates = HashSet::<&u8>::new();
let mut sum = 0;
for l in &lines { // <= HERE iter over String references which lives outside the for loop
if candidates.len()==0 {
candidates = HashSet::<&u8>::from_iter(l.as_bytes());
println!("candidates = {:?}", candidates);
} else if l.len() == 0 {
// end of group
sum = sum + candidates.len();
candidates = HashSet::<&u8>::new();
} else {
let h2 = HashSet::<&u8>::from_iter(l.as_bytes());
candidates = candidates.intersection(&h2).copied().collect();
println!("candidates = {:?}", candidates);
}
println!("{}", l);
}
第二种解决方案是复制 l 字符串。
let mut candidates = HashSet::<u8>::new();
let mut sum = 0;
for l in lines { // lines is Vec<String>
if candidates.len()==0 {
candidates = HashSet::<u8>::from_iter(l.clone().into_bytes());
println!("candidates = {:?}", candidates);
} else if l.len() == 0 {
// end of group
sum = sum + candidates.len();
candidates = HashSet::<u8>::new();
} else {
let h2 = HashSet::<u8>::from_iter(l.clone().into_bytes());
candidates = candidates.intersection(&h2).copied().collect();
println!("candidates = {:?}", candidates);
}
println!("{}", l);
}
candidates
可以包含来自上一个循环迭代的对 l
的引用,但是 l
在每次循环迭代结束时被删除,因此会出现编译错误。你可以通过使用 into_bytes
而不是 as_bytes
来避免所有这些麻烦,这样你就可以获得拥有的值而不是引用。这是清理后的重构版本:
use std::collections::HashSet;
fn example(lines: Vec<String>) {
let mut candidates: HashSet<u8> = HashSet::new();
let mut sum = 0;
for line in lines {
dbg!(&line);
let h2: HashSet<u8> = line.into_bytes().into_iter().collect();
if candidates.is_empty() {
candidates = h2;
} else if h2.is_empty() {
sum += candidates.len();
candidates = HashSet::new();
} else {
candidates = candidates.intersection(&h2).copied().collect();
}
dbg!(&candidates);
}
}
我正在通过一些编程练习自学 Rust。这里我有一个 Vec<String>
我从一个文件中读出,我试图将每行中的字母放在 HashSet
中,然后取所有行的交集。
当我这样做时,我收到一条错误消息,提示我的循环变量寿命不够长。
我直觉哪里出了问题——我有一个变量 l
,它的生命周期是循环的一次迭代,另一个变量 candidates 的生命周期是整个循环,第二个变量是从首先。但是我该如何解决这个问题?
let mut candidates = HashSet::<&u8>::new();
let mut sum = 0;
for l in lines { // lines is Vec<String>
if candidates.len()==0 {
candidates = HashSet::<&u8>::from_iter(l.as_bytes());
println!("candidates = {:?}", candidates);
} else if l.len() == 0 { // error message "borrow later used here"
// end of group
sum = sum + candidates.len();
candidates = HashSet::<&u8>::new();
} else {
let h2 = HashSet::<&u8>::from_iter(l.as_bytes()); // error message "borrowed value does not live long enough"
candidates = candidates.intersection(&h2).copied().collect();
println!("candidates = {:?}", candidates);
}
println!("{}", l);
}
我尝试复制 l
let mut l2:String = "".to_string();
for l in lines {
if candidates.len()==0 {
l2 = l.to_string();
candidates = HashSet::<&u8>::from_iter(l2.as_bytes());
但是我得到了一个不同的错误 error[E0506]: cannot assign to l2 because it is borrowed
。
as_bytes
将您的 l
字符串转换为字节切片。切片是对连续元素序列的引用。编译器指出在您的 for 循环结束时,引用无效。
一种解决方案是使用 &lines
:
let mut candidates = HashSet::<&u8>::new();
let mut sum = 0;
for l in &lines { // <= HERE iter over String references which lives outside the for loop
if candidates.len()==0 {
candidates = HashSet::<&u8>::from_iter(l.as_bytes());
println!("candidates = {:?}", candidates);
} else if l.len() == 0 {
// end of group
sum = sum + candidates.len();
candidates = HashSet::<&u8>::new();
} else {
let h2 = HashSet::<&u8>::from_iter(l.as_bytes());
candidates = candidates.intersection(&h2).copied().collect();
println!("candidates = {:?}", candidates);
}
println!("{}", l);
}
第二种解决方案是复制 l 字符串。
let mut candidates = HashSet::<u8>::new();
let mut sum = 0;
for l in lines { // lines is Vec<String>
if candidates.len()==0 {
candidates = HashSet::<u8>::from_iter(l.clone().into_bytes());
println!("candidates = {:?}", candidates);
} else if l.len() == 0 {
// end of group
sum = sum + candidates.len();
candidates = HashSet::<u8>::new();
} else {
let h2 = HashSet::<u8>::from_iter(l.clone().into_bytes());
candidates = candidates.intersection(&h2).copied().collect();
println!("candidates = {:?}", candidates);
}
println!("{}", l);
}
candidates
可以包含来自上一个循环迭代的对 l
的引用,但是 l
在每次循环迭代结束时被删除,因此会出现编译错误。你可以通过使用 into_bytes
而不是 as_bytes
来避免所有这些麻烦,这样你就可以获得拥有的值而不是引用。这是清理后的重构版本:
use std::collections::HashSet;
fn example(lines: Vec<String>) {
let mut candidates: HashSet<u8> = HashSet::new();
let mut sum = 0;
for line in lines {
dbg!(&line);
let h2: HashSet<u8> = line.into_bytes().into_iter().collect();
if candidates.is_empty() {
candidates = h2;
} else if h2.is_empty() {
sum += candidates.len();
candidates = HashSet::new();
} else {
candidates = candidates.intersection(&h2).copied().collect();
}
dbg!(&candidates);
}
}