【问题标题】:Build HashSet from a vector in Rust从 Rust 中的向量构建 HashSet
【发布时间】:2017-02-09 17:21:57
【问题描述】:

我想从Vec<u8> 构建一个HashSet<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。

【问题讨论】:

  • 仅供参考:在您的第一个代码中,您不需要克隆向量,只需将其声明为可变。通过let mut victim = vec; 或在参数列表中通过:fn vec_to_set(mut vec: Vec&lt;u8&gt;)
  • 您没有正确使用 O 表示法。 O(n) = O(2n) = O(3n) = O(c*n)。关键是常数无关紧要。我认为您的意思很清楚,但您可能应该只说“2n memory”之类的。
  • 谢谢 Lii,如果 O(n) == O(2n) 那么正确的表达方式是什么?能够比较n2n 似乎很有用。谢谢。

标签: vector rust hashset


【解决方案1】:

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

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

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

将其称为hashset(&amp;v),其中vVec&lt;u8&gt; 或其他强制切片的东西。

当然有更多的方法来写这个,通用的等等,但这个答案坚持只是介绍我想要关注的东西。

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

【讨论】:

  • 这不再编译了。
【解决方案2】:

移动数据所有权

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();

【讨论】:

  • collect 使用 FromIterator — 这与上述两个答案相同,只是更冗长。
  • 修复了类型错误。此代码不需要在转换代码中重复HashSet
  • 原始答案中也没有重复HashSet。他们的代码:let hash_set = HashSet::&lt;_&gt;::from_iter(vec); 与您的代码:let hash_set: HashSet&lt;usize&gt; = vec.into_iter().collect()
  • 您删除了第一个示例中的类型以隐藏 HashSet 代码 1 的重复:let hash_set: HashSet&lt;usize&gt; = HashSet::&lt;_&gt;::from_iter(vec); 代码 2:let hash_set: HashSet&lt;usize&gt; = vec.into_iter().collect() 示例恢复
【解决方案3】:

以下应该可以很好地工作;它满足您的要求:

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() 不存在

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2019-12-06
    • 2022-11-22
    相关资源
    最近更新 更多