我有一个相当简单的函数(我们称之为交集),它接受两个 &[u32]
类型的参数我希望返回类型为 &[u32]
。该函数接受两个切片(数组?),并返回一个新切片(数组?),其中包含两个切片中的元素。
pub fn intersection<'a>(left: &'a [u32], right: &'a [u32]) -> &'a [u32] {
let left_set: HashSet<u32> = left.iter().cloned().collect();
let right_set: HashSet<u32> = right.iter().cloned().collect();
// I can't figure out how to get a
// `&[u32]` output idiomatically
let result: &[u32] = left_set
.intersection(&right_set)
.into_iter()
.....
.....
result //<- this is a slice
}
我想我可以做一些类似创建 Vec<u32>
的事情但借用检查器不喜欢我归还Vec<u32>
.
pub fn intersection<'a>(left: &'a [u32], right: &'a [u32]) -> &'a [u32] {
.....
.....
let mut result: Vec<u32> = left_set
.intersection(&right_set)
.into_iter()
.cloned()
.collect();
result.sort();
result.as_slice() //<-- ERROR cannot return reference to local variable
// `result` returns a reference to data owned by the current function
}
我可能在这里错过了一个技巧。关于如何在 Rust 中惯用地执行此操作有什么建议吗?
最佳答案
This function takes in two arrays
不,需要两个切片。
I'm probably missing a trick here. Any advice on how to do this idiomatically in Rust?
没有任何技巧,你也做不到。切片是借用的一种形式,根据定义,切片指的是某些其他集合(静态内存、向量、数组……)拥有的内存。
这意味着像所有其他借用一样,如果它从本地作用域借用数据,则无法返回,这将导致悬空指针(因为当作用域结束时,实际所有者将被销毁)。
正确的做法是只返回一个Vec
:
pub fn intersection<'a>(left: &'a [u32], right: &'a [u32]) -> Vec<u32> {
left.iter().collect::<HashSet<_>>().intersection(
&right.iter().collect()
).map(|&&v| v).collect()
}
或者,如果其中一个切片是另一个切片的子集是很常见的并且您很乐意支付支票(可能是因为您可以使用位图之类的东西),您可以返回一个Cow
,在子集情况下返回子集切片:
pub fn intersection<'a>(left: &'a [u32], right: &'a [u32]) -> Cow<'a, [u32]> {
if issubset(left, right) {
Cow::Borrowed(left)
} else if issubset(right, left) {
Cow::Borrowed(right)
} else {
Cow::Owned(
left.iter().collect::<HashSet<_>>().intersection(
&right.iter().collect()
).map(|&&v| v).collect()
)
}
}
关于rust - 从函数返回 `u32` 的数组/切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75394760/