如何从 HashSet 中形成一个切片?
How do I form a slice from a HashSet?
结构定义为:
struct Node {
set: HashSet<usize>,
// other fields omitted
}
我必须为特征(兼容性问题)实现一个函数,它需要return集合中的所有元素作为一个切片。
我知道类似以下功能的功能将不起作用:
impl Node {
pub fn set_slice(&self) -> &[usize] {
let elems: Vec<_> = self.set.iter().cloned().collect();
&elems[..]
}
}
问题是:
error[E0597]: `elems` does not live long enough
--> src/main.rs:11:10
|
11 | &elems[..]
| ^^^^^ borrowed value does not live long enough
12 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 9:5...
--> src/main.rs:9:5
|
9 | / pub fn set_slice(&self) -> &[usize] {
10 | | let elems: Vec<_> = self.set.iter().cloned().collect();
11 | | &elems[..]
12 | | }
| |_____^
我知道这个要求听起来很奇怪。尽管我必须这样做,但有什么 'good' 方法可以做到这一点吗?
如果可能的话,我想保留 HashSet
容器用于 O(1) 查找,我不想为了节省内存而引入新的结构成员。
不,您的要求在安全 Rust 中是 100% 完全不可能的。
A HashSet
/ HashMap
没有连续的数据集合,因此无法从中获取切片。
如果你能改变一些事情,那么你就有了选择。
如果可以存储 Vec
并且方法是 &mut self
:
,则可以 HashSet
的 "render a view"
struct Node {
set: HashSet<usize>,
view: Vec<usize>,
// other fields omitted
}
impl Node {
pub fn set_slice(&mut self) -> &[usize] {
self.view.clear();
self.view.extend(self.set.iter().cloned());
&self.view
}
}
您可以 return 一个 Cow
可以借用或拥有的:
use std::borrow::Cow;
impl Node {
pub fn set_slice(&self) -> Cow<[usize]> {
self.set.iter().cloned().collect::<Vec<_>>().into()
}
}
你可以return an iterator over the values:
impl Node {
pub fn set_slice<'a>(&'a self) -> impl Iterator<Item = &'a usize> + 'a {
self.set.iter()
}
}
可能a crate使用紧密打包的Vec
作为其后备存储,然后可以作为切片公开。
这在简单(基本)方式中是不可能的。
Box
、mut static
可以做到这一点,但我建议修改您的特质和 return 如下例所示:
您可以在特征中使用 AsRef<[T]>
而不是 &[usize]
。或者只是 return 一个迭代器。
struct Node {
set: HashSet<usize>,
}
trait SetSlice {
type Slice: AsRef<[usize]>;
fn get_slice_cloned(&self) -> Self::Slice;
}
impl SetSlice for Node {
type Slice = Vec<usize>;
fn get_slice_cloned(&self) -> Self::Slice { self.set.iter().cloned().collect() }
}
// there we use auto-impl of Iterator trait
// and return the iter.
// NOTE: we cannot use auto-impl in trait methods.
impl Node {
fn get_neat_iter(&self) -> impl Iterator<Item = &usize> { self.set.iter() }
}
fn need_slice(slice: &[usize]) {}
fn main() {
let n = Node { set: Default::default(), };
// as_ref
let all = n.get_slice_cloned();
need_slice(all.as_ref());
// iter-way
let all: Vec<_> = n.get_neat_iter().cloned().collect();
need_slice(&all);
}
这只是众多方式中的两种。
结构定义为:
struct Node {
set: HashSet<usize>,
// other fields omitted
}
我必须为特征(兼容性问题)实现一个函数,它需要return集合中的所有元素作为一个切片。
我知道类似以下功能的功能将不起作用:
impl Node {
pub fn set_slice(&self) -> &[usize] {
let elems: Vec<_> = self.set.iter().cloned().collect();
&elems[..]
}
}
问题是:
error[E0597]: `elems` does not live long enough
--> src/main.rs:11:10
|
11 | &elems[..]
| ^^^^^ borrowed value does not live long enough
12 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 9:5...
--> src/main.rs:9:5
|
9 | / pub fn set_slice(&self) -> &[usize] {
10 | | let elems: Vec<_> = self.set.iter().cloned().collect();
11 | | &elems[..]
12 | | }
| |_____^
我知道这个要求听起来很奇怪。尽管我必须这样做,但有什么 'good' 方法可以做到这一点吗?
如果可能的话,我想保留 HashSet
容器用于 O(1) 查找,我不想为了节省内存而引入新的结构成员。
不,您的要求在安全 Rust 中是 100% 完全不可能的。
A HashSet
/ HashMap
没有连续的数据集合,因此无法从中获取切片。
如果你能改变一些事情,那么你就有了选择。
如果可以存储 Vec
并且方法是 &mut self
:
HashSet
的 "render a view"
struct Node {
set: HashSet<usize>,
view: Vec<usize>,
// other fields omitted
}
impl Node {
pub fn set_slice(&mut self) -> &[usize] {
self.view.clear();
self.view.extend(self.set.iter().cloned());
&self.view
}
}
您可以 return 一个 Cow
可以借用或拥有的:
use std::borrow::Cow;
impl Node {
pub fn set_slice(&self) -> Cow<[usize]> {
self.set.iter().cloned().collect::<Vec<_>>().into()
}
}
你可以return an iterator over the values:
impl Node {
pub fn set_slice<'a>(&'a self) -> impl Iterator<Item = &'a usize> + 'a {
self.set.iter()
}
}
可能a crate使用紧密打包的Vec
作为其后备存储,然后可以作为切片公开。
这在简单(基本)方式中是不可能的。
Box
、mut static
可以做到这一点,但我建议修改您的特质和 return 如下例所示:
您可以在特征中使用 AsRef<[T]>
而不是 &[usize]
。或者只是 return 一个迭代器。
struct Node {
set: HashSet<usize>,
}
trait SetSlice {
type Slice: AsRef<[usize]>;
fn get_slice_cloned(&self) -> Self::Slice;
}
impl SetSlice for Node {
type Slice = Vec<usize>;
fn get_slice_cloned(&self) -> Self::Slice { self.set.iter().cloned().collect() }
}
// there we use auto-impl of Iterator trait
// and return the iter.
// NOTE: we cannot use auto-impl in trait methods.
impl Node {
fn get_neat_iter(&self) -> impl Iterator<Item = &usize> { self.set.iter() }
}
fn need_slice(slice: &[usize]) {}
fn main() {
let n = Node { set: Default::default(), };
// as_ref
let all = n.get_slice_cloned();
need_slice(all.as_ref());
// iter-way
let all: Vec<_> = n.get_neat_iter().cloned().collect();
need_slice(&all);
}
这只是众多方式中的两种。