2016-10-01 180 views
8

我想从Vec<u8>构建HashSet<u8>。我想做到这一点从Rust中的矢量生成HashSet

  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。

+1

代码和错误消息不匹配。你的意思是'iter()' – bluss

+0

仅供参考:在你的第一个代码中,你不需要克隆载体,你只需要声明它是可变的。可以通过'let mut victim = vec;'或者在参数列表中使用''vec_to_set(mut vec:Vec )''。 –

+4

您没有正确使用* O *表示法。 _O(n)= O(2n)= O(3n)= O(c * n)_。关键是常数不重要。我认为这很清楚你的意思,但你应该说只是“_2n_记忆”或其他。 – Lii

回答

11

另一种选择:

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

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,即它没有所有权语义。

11

以下应该很好地工作;它满足您的要求:在实施IntoIterator类型

use std::iter::FromIterator; 

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

from_iter()作品,所以Vec说法是足够的。

补充说明:

  • 你不需要明确return函数结果;你只需要省略最后一个表达式的分号在它的身上

  • 我不知道你正在使用的锈的版本,但在当前的稳定(1.12)to_iter()不存在