从Rust中的向量构建HashSet

问题描述 投票:21回答:3

我想从HashSet<u8>建立一个Vec<u8>。我想这样做

  1. 在一行代码中,
  2. 仅复制一次数据,
  3. 仅使用2n记忆,

但我唯一可以编译的就是这段...垃圾,我认为两次复制数据并使用3n内存。

fn vec_to_set(vec: Vec<u8>) -> HashSet<u8> {
    let mut victim = vec.clone();
    let x: HashSet<u8> = victim.drain(..).collect();
    return x;
}

我希望写一些简单的东西,比如:

fn vec_to_set(vec: Vec<u8>) -> HashSet<u8> {
    return HashSet::from_iter(vec.iter());
}

但那不会编译:

error[E0308]: mismatched types
 --> <anon>:5:12
  |
5 |     return HashSet::from_iter(vec.iter());
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found &u8
  |
  = note: expected type `std::collections::HashSet<u8>`
  = note:    found type `std::collections::HashSet<&u8, _>`

..我真的不明白错误信息,可能是因为我需要RTFM。

vector rust hashset
3个回答
20
投票

因为操作不需要使用矢量¹,我认为它不应该消耗它。这只会导致程序中其他地方的额外复制:

use std::collections::HashSet;
use std::iter::FromIterator;

fn hashset(data: &[u8]) -> HashSet<u8> {
    HashSet::from_iter(data.iter().cloned())
}

称之为hashset(&v),其中vVec<u8>或其他强迫切片的东西。

当然有更多的方法来写这个,通用的和所有这些,但这个答案坚持只是介绍我想要关注的事情。

¹这是基于元素类型u8Copy,即它没有所有权语义。


20
投票

以下应该很好地工作;它符合您的要求:

use std::collections::HashSet;
use std::iter::FromIterator;

fn vec_to_set(vec: Vec<u8>) -> HashSet<u8> {
    HashSet::from_iter(vec)
}

from_iter()适用于实现IntoIterator的类型,所以Vec论证就足够了。

补充说明:

  • 你不需要明确的return函数结果;你只需要在其体内的最后一个表达式中省略分号
  • 我不确定你使用的是哪个版本的Rust,但是目前的稳定版(1.12)to_iter()不存在

1
投票

移动数据所有权

let vec: Vec<usize> = vec![1, 2, 3, 4];
let hash_set: HashSet<usize> = vec.into_iter().collect();

克隆数据

let vec: Vec<usize> = vec![1, 2, 3, 4];
let hash_set: HashSet<usize> = vec.iter().cloned().collect();
© www.soinside.com 2019 - 2024. All rights reserved.