Создайте HashSet из вектора в Rust
Я хочу построить HashSet<u8>
из Vec<u8>
. Я бы хотел сделать это
- в одной строке кода,
- копирование данных только один раз,
- используя только
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
Поскольку операция не должна потреблять вектор¹, я думаю, что она не должна потреблять его. Это приводит только к дополнительному копированию в другом месте программы:
use std::collections::HashSet;
use std::iter::FromIterator;
fn hashset(data: &[u8]) -> HashSet<u8> {
HashSet::from_iter(data.iter().cloned())
}
Назовите его как hashset(&v)
, где v
- это Vec<u8>
или другое, что приводит к срезу.
Конечно, есть и другие способы написать это, быть универсальным и тому подобное, но этот ответ придерживается только того, на чем я хотел бы остановиться.
Это основано на том, что тип элемента u8
- Copy
, то есть он не имеет семантики владения.
Ответ 2
Следующее должно работать хорошо; он отвечает вашим требованиям:
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()
не существует
Ответ 3
Перемещение владения данными
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();