Проверка двух HashMaps на идентичный набор ключей в Rust - PullRequest
1 голос
/ 30 октября 2019

Предположим, у меня есть две HashMaps (или любая структура карты, в которой ключи сопоставляются с чем-то другим), map1 и map2, и я хочу убедиться, что они имеют идентичный набор ключей. Обратите внимание, что ключи имеют тот же тип на картах, но значения равны , а не .

Моя первая попытка это была просто:

map1.keys().eq(map2.keys())

и, хотя это сработало first time, функция eq для итераторов (понятно), похоже, сравнивает ключи в порядкеитератором, а не проверкой существования ключа где-либо во втором итераторе . Это в сочетании с тем фактом, что HashMap :: keys () создает итератор, в котором порядок ключей является недетерминированным , означает, что функция равенства часто не срабатывает, даже если множества (в теории множеств)смысла) клавиш идентичны.

Итак, моей следующей попыткой было создать функцию, которая выполняла бы следующее:

fn keys_match<T:std::cmp::Eq + std::hash::Hash,U,V>(map1:&HashMap<T,U>, map2:&HashMap<T,V>) -> bool {
  // Make sure that map1.keys() ⊆ map2.keys()
  for key in map1.keys() {
    match map2.get(key) {
      None => return false,
      Some(_) => {}
    }
  }
  // If map1.keys() ⊆ map2.keys() and their sizes equal, then the sets are equal
  map1.len() == map2.len()
}

Примечание для начинающих в Rust: Моя первая попытка была на самом деле сзнание того, что ключи на картах были типа String, поэтому моя сигнатура функции была:

fn keys_match<T,U>(map1:&HashMap<String,T>, map2:&HashMap<String,U>) -> bool

, пока я не понял, что могу даже обобщить общий тип ключа , потребовав от нихимеют черты Eq и Hash.

Вопрос: Есть ли более краткий способ сделать это в Rust?

1 Ответ

6 голосов
/ 30 октября 2019

Есть ли более краткий способ сделать это в Rust?

fn keys_match<T: Eq + Hash, U, V>(
    map1: &HashMap<T, U>, 
    map2: &HashMap<T, V>,
) -> bool {
    map1.len() == map2.len() && map1.keys().all(|k| map2.contains_key(k))
}

( Детская площадка )

Этот код имеет три улучшения по сравнению с вашим кодом:

  • Использование Iterator::all значительно сокращает код.
  • Использование HashMap::contains_key лучше, чем проверка результата HashMap::get.
  • Сначала проверяется длина, так как это дешевый тест, и его нужно сделать первым.
...