Введение
В этом лабе мы исследуем функциональность структуры данных HashSet в Rust, которая гарантирует уникальные элементы и может выполнять операции, такие как объединение, разность, пересечение и симметрическая разность для множеств.
Примечание: Если в лабе не указано имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать
main.rs, скомпилировать и запустить его с помощьюrustc main.rs &&./main.
HashSet
Рассмотрите HashSet как HashMap, где нас интересуют только ключи (на самом деле HashSet<T> - это просто обертка вокруг HashMap<T, ()>).
"Для чего это?" - вы задаете вопрос. "Я мог бы просто хранить ключи в Vec".
Уникальная особенность HashSet заключается в том, что гарантируется отсутствие дублирующихся элементов. Именно это контракт, который выполняет любая коллекция множества. HashSet - это всего лишь одна реализация. (см. также: BTreeSet)
Если вы вставите значение, которое уже присутствует в HashSet (то есть новое значение равно существующему и у них одинаковая хэш-сумма), то новое значение заменит старое.
Это очень полезно, когда вы никогда не хотите иметь более одного экземпляра чего-либо, или когда хотите знать, есть ли у вас уже что-то.
Но множества могут делать гораздо больше.
У множеств есть 4 основных операции (все следующие вызовы возвращают итератор):
union: получить все уникальные элементы обоих множеств.difference: получить все элементы, которые находятся в первом множестве, но не во втором.intersection: получить все элементы, которые находятся только в обоих множествах.symmetric_difference: получить все элементы, которые находятся в одном множестве или в другом, но не в обоих одновременно.
Попробуйте все эти операции в следующем примере:
use std::collections::HashSet;
fn main() {
let mut a: HashSet<i32> = vec![1i32, 2, 3].into_iter().collect();
let mut b: HashSet<i32> = vec![2i32, 3, 4].into_iter().collect();
assert!(a.insert(4));
assert!(a.contains(&4));
// `HashSet::insert()` возвращает false, если
// уже было такое значение.
assert!(b.insert(4), "Value 4 is already in set B!");
// FIXME ^ Comment out this line
b.insert(5);
// Если тип элементов коллекции реализует `Debug`,
// то коллекция реализует `Debug`.
// Обычно она выводит свои элементы в формате `[elem1, elem2,...]`
println!("A: {:?}", a);
println!("B: {:?}", b);
// Выведет [1, 2, 3, 4, 5] в произвольном порядке
println!("Union: {:?}", a.union(&b).collect::<Vec<&i32>>());
// Это должно вывести [1]
println!("Difference: {:?}", a.difference(&b).collect::<Vec<&i32>>());
// Выведет [2, 3, 4] в произвольном порядке.
println!("Intersection: {:?}", a.intersection(&b).collect::<Vec<&i32>>());
// Выведет [1, 5]
println!("Symmetric Difference: {:?}",
a.symmetric_difference(&b).collect::<Vec<&i32>>());
}
(Примеры адаптированы из документации.)
Резюме
Поздравляем! Вы завершили лабу по HashSet. Вы можете практиковаться в более многих лабах в LabEx, чтобы улучшить свои навыки.