// https://cses.fi/problemset/task/1621
use std::collections::HashSet;
fn main() {
let mut inp: String = String::new();
std::io::stdin()
.read_line(&mut inp)
.expect("Error in input");
let n: u64 = inp.trim().parse().expect("Error in parsing to int");
inp.clear();
std::io::stdin()
.read_line(&mut inp)
.expect("Error in input");
let x: Vec<u64> = inp
.split_whitespace()
.map(|s| s.parse().expect("Error in input"))
.collect();
println!("x: {:?}", x);
let mut map: HashSet<u64> = HashSet::new();
// Use a for loop to insert values into the HashSet
for key in &x {
map.insert(*key);
}
println!("{}", map.len());
println!("x: {:?}", x);
println!("map: {:?}", map);
}
结果:
5
1 2 3 3
x: [1, 2, 3, 3]
3
x: [1, 2, 3, 3]
map: {2, 1, 3}
有人可以解释一下所有权吗
输入 &x { 地图.插入(*键); }
我们是否在这里使用引用运算符创建密钥的副本?如果数组的元素是 String 类型怎么办?
在
for key in &x { map.insert(*key); }
行中,您正在迭代对向量x
中元素的引用。 &
中的&x
表示“借用x
”或“获取对x
的引用”。这允许您访问 x
的元素,而无需获取它们的所有权。
当您执行
*key
时,您将取消引用引用以获取实际值。在这种情况下,因为 u64
实现了 Copy
特征,这实际上创建了该值的副本。这就是为什么您可以毫无问题地将其插入HashSet
。
如果数组的元素属于
String
类型,您将无法简单地取消引用键来获取副本,因为 String
不实现 Copy
特性。相反,您必须克隆字符串以获得可以插入到 HashSet
中的副本。这看起来像 for key in &x { map.insert(key.clone()); }
。
或者,如果在此之后您不需要原始向量
x
,您可以获取字符串的所有权并将它们移动到 HashSet
中,而无需克隆。这看起来像for key in x { map.insert(key); }
。请注意,这将使 x
之后为空。