Переместить одну запись, которая соответствует предикату, из HashMap, когда ключ не является клонируемым - PullRequest
2 голосов
/ 28 марта 2019

Я пишу функцию, которая работает с HashMap, и в различных точках функции я хочу проверить, соответствует ли какое-либо из значений на карте условию, и если оно есть, возвращает ключ только для одного из записи, соответствующие условию.

До сих пор я пытался сначала выполнить итерации по ссылкам, чтобы проверить мое состояние, а затем использовать remove_entry для получения собственной копии ключа, а не заимствования:

use std::{collections::HashMap, hash::Hash};

fn remove_first_odd<K: Hash + Eq>(map: &mut HashMap<K, u64>) -> Option<K> {
    let maybe_entry = map.iter().find(|(_, &value)| value & 1 == 1);

    match maybe_entry {
        Some((key_ref, _value_ref)) => {
            let (key_owned, _value_owned) = map.remove_entry(key_ref).unwrap();
            Some(key_owned)
        }
        None => None,
    }
}

но это не проходит проверку заимствования, потому что я не могу изменить карту, пока я все еще держу ссылку на один из ключей в ней:

error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable
 --> src/lib.rs:8:45
  |
4 |     let maybe_entry = map.iter().find(|(_, &value)| value & 1 == 1);
  |                       --- immutable borrow occurs here
...
8 |             let (key_owned, _value_owned) = map.remove_entry(key_ref).unwrap();
  |                                             ^^^^------------^^^^^^^^^
  |                                             |   |
  |                                             |   immutable borrow later used by call
  |                                             mutable borrow occurs here

Я считаю, что это возможно, поскольку до тех пор, пока remove_entry только разыменовывает мой ключ до мутации, а не после, это должно быть нормально.

Так есть ли безопасный API для этого? Если нет, то можно ли его создать?

Обратите внимание, что:

  • Я не могу клонировать свои ключи, потому что они являются общими без привязки клону
  • Я не могу потреблять HashMap с чем-то вроде .into_iter()
  • Мне нужно удалить только одну запись, а не все записи, которые соответствуют
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...