Как мне расширить HashSet с помощью другого HashSet ?

#string #rust #hashset #ownership

#строка #Ржавчина #hashset #владение

Вопрос:

Когда я пытаюсь расширить a HashSet<String> с помощью другого HashSet<String> :

 use std::collections::HashSet;
let mut a = HashSet::new();
a.insert("foo".to_owned());
let mut b = HashSet::new();
b.insert("bar".to_owned());
let c = a.extend(amp;b);
 

Я получаю:

 error[E0271]: type mismatch resolving `<amp;HashSet<String> as IntoIterator>::Item == String`
 --> src/main.rs:7:11
  |
7 | let c = a.extend(amp;b);
  |           ^^^^^^ expected reference, found struct `String`
  |
  = note: expected reference `amp;String`
                found struct `String`
 

Как мне это сделать?

Комментарии:

1. Принятый ответ на другой вопрос не касается того, что задано здесь, потому что он рекомендует a.extend(amp;b) , какой сбой для операции. Это работает в другом ответе, потому что в другом ответе используются элементы set, которые Copy . (Я был немного удивлен, что a.extend(amp;b) works for элементы Copy`, интересно, какой механизм это позволяет.)

Ответ №1:

HashSet::extend() исходит из Extend признака и, следовательно, принимает любой итератор (или итерируемый), а не только набор.

Если вы передаете ему ссылку на набор, эта ссылка является итеративной, но итератор создает ссылки на элементы набора — в данном случае amp;String . Поскольку HashSet::<String>::extend() ожидается, что итератор, который создает фактические строки, не компилируется. Есть два способа устранить проблему:

  • передавая set b extend по значению: a.extend(b) ;
  • путем создания явного итератора из b использования b.iter() и клонирования создаваемых им значений : a.extend(b.iter().cloned()) .

В первом варианте b он будет использоваться и, следовательно, больше не будет использоваться вызывающей стороной, но строки из него будут использоваться повторно a . Во втором варианте b он останется пригодным для использования, но его строки будут скопированы для хранения a .

Обратите внимание, что ни в одном из вариантов не имеет смысла фиксировать возвращаемое значение extend() , поскольку оно работает побочным эффектом и не возвращает полезное значение.