Construir HashSet a partir de un vector en Rust
(3)
Quiero construir un HashSet<u8>
partir de un Vec<u8>
. Me gustaria hacer esto
- en una línea de código,
- copiando los datos una sola vez,
- usando solo
2n
memoria,
pero lo único que puedo compilar es esta pieza de ... basura, que creo que copia los datos dos veces y usa la memoria 3n
.
fn vec_to_set(vec: Vec<u8>) -> HashSet<u8> {
let mut victim = vec.clone();
let x: HashSet<u8> = victim.drain(..).collect();
return x;
}
Esperaba escribir algo simple, como este:
fn vec_to_set(vec: Vec<u8>) -> HashSet<u8> {
return HashSet::from_iter(vec.iter());
}
pero eso no compilará
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, _>`
.. y realmente no entiendo el mensaje de error, probablemente porque necesito RTFM.
Debido a que la operación no necesita consumir el vector¹, creo que no debería consumirlo. Eso solo conduce a copias adicionales en otro lugar del programa:
use std::collections::HashSet;
use std::iter::FromIterator;
fn hashset(data: &[u8]) -> HashSet<u8> {
HashSet::from_iter(data.iter().cloned())
}
Llámelo como hashset(&v)
donde v
es un Vec<u8>
u otra cosa que obliga a un segmento.
Por supuesto, hay más formas de escribir esto, de ser genérico y todo eso, pero esta respuesta se limita a presentar solo aquello en lo que quería centrarme.
Esto se basa en que el tipo de elemento u8
es Copy
, es decir, no tiene semántica de propiedad.
Lo siguiente debería funcionar bien; cumple con tus requerimientos:
use std::collections::HashSet;
use std::iter::FromIterator;
fn vec_to_set(vec: Vec<u8>) -> HashSet<u8> {
HashSet::from_iter(vec)
}
from_iter()
trabaja en tipos que implementan IntoIterator
, por lo que un argumento Vec
es suficiente.
Observaciones adicionales:
no necesita
return
explícitamente los resultados de la función; solo necesitas omitir el punto y coma en la última expresión de su cuerpoNo estoy seguro de qué versión de Rust está utilizando, pero en la versión actual (1.12)
to_iter()
no existe
Moviendo la propiedad de los datos
let vec: Vec<usize> = vec![1, 2, 3, 4];
let hash_set: HashSet<usize> = vec.into_iter().collect();
Datos de clonacion
let vec: Vec<usize> = vec![1, 2, 3, 4];
let hash_set: HashSet<usize> = vec.iter().cloned().collect();