vector rust hashset

Construir HashSet a partir de un vector en Rust



(3)

Quiero construir un HashSet<u8> partir de un Vec<u8> . Me gustaria hacer esto

  1. en una línea de código,
  2. copiando los datos una sola vez,
  3. 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 cuerpo

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