HashSet

集合 (set) 是一個數學上的概念,表示一群不重覆的無序物件,Rust 的 HashSet 內部的確是以 HashMap 來做為儲存資料的容器。雖然 HashSet 內部使用 HashMap,但簡化了介面,使用者不需要直接操作 HashMap。

  1. use std::collections::HashSet;
  2. fn main() {
  3. // Create an empty set
  4. let mut set = HashSet::new();
  5. // Insert item into the set
  6. set.insert("C++");
  7. set.insert("Java");
  8. set.insert("Python");
  9. set.insert("Rust");
  10. set.insert("Go");
  11. // Check the property of the set
  12. assert_eq!(set.len(), 5);
  13. assert_eq!(set.contains("Rust"), true);
  14. assert_eq!(set.contains("Lisp"), false);
  15. // Remove item from the set
  16. set.remove("Python");
  17. // Check the property of the set
  18. assert_eq!(set.len(), 4);
  19. assert_eq!(set.contains("Rust"), true);
  20. assert_eq!(set.contains("Python"), false);
  21. }

集合可以實現一些集合論的二元操作,像是聯集 (unino)、交集 (intersection)、差集 (difference) 等。以下用實例展示這些操作:

  1. use std::collections::HashSet;
  2. fn main() {
  3. // Get two sets from two arrays
  4. let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
  5. let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
  6. // Get the union of the two sets
  7. let union: HashSet<_> = a.union(&b).cloned().collect();
  8. assert_eq!(union, [1, 2, 3, 4].iter().cloned().collect());
  9. // Get the intersection of the two sets
  10. let intersection: HashSet<_> = a.intersection(&b).cloned().collect();
  11. assert_eq!(intersection, [2, 3].iter().cloned().collect());
  12. // Get the difference of a from b
  13. let diff: HashSet<_> = a.difference(&b).cloned().collect();
  14. assert_eq!(diff, [1].iter().cloned().collect());
  15. }

(案例選讀) 位數不重覆的數字 在本節中,我們處理以下的問題:選出位數不重覆的數字。例如:435 的三個數字都不重覆,就是一個符合條件的數字;而 919 則因為有重覆的 9 不符合本題目的條件。我們將某個數字拆開,每個位數各個放入集合中,若集合的長度大於等於數字的位數,則代表該數字的位數沒有重覆,符合我們的條件。

  1. use std::io;
  2. use std::io::Write;
  3. use std::process;
  4. use std::collections::HashSet;
  5. fn main() {
  6. // Prompt for user input
  7. print!("Input a number: ");
  8. let _ = io::stdout().flush();
  9. // Receive user input
  10. let mut input = String::new();
  11. io::stdin()
  12. .read_line(&mut input)
  13. .expect("failed to read from stdin");
  14. // Parse the number
  15. let n = match input.trim().parse::<u32>() {
  16. Ok(i) => i,
  17. Err(_) => {
  18. println!("Invalid integer");
  19. // Exit the program with abnormal status code
  20. process::exit(1);
  21. }
  22. };
  23. let x: i32 = 10;
  24. for i in 1..(x.pow(n)) {
  25. /* Convert number to an iterator of char.
  26. Then, insert char to set. */
  27. let num_string = i.to_string();
  28. let mut chars = num_string.chars();
  29. let mut set = HashSet::new();
  30. let mut c = chars.next();
  31. while c != None {
  32. set.insert(c);
  33. c = chars.next();
  34. }
  35. // Get the digit number of i
  36. let mut digit = 0;
  37. let mut j = i;
  38. while j > 0 {
  39. j = j / 10;
  40. digit += 1;
  41. }
  42. // Check whether i fits our criteria
  43. if set.len() as i32 >= digit {
  44. // Show i in console
  45. print!("{} ", i);
  46. }
  47. }
  48. // Print tailing newline
  49. println!("");
  50. }