Как переименовать все ключи в serde_json :: Map?

Допустим, у меня есть &mut std::collections::HashMap, и я хочу перевести все клавиши в верхний регистр. Следующий код делает свое дело:

use std::collections::HashMap;

fn keys_to_upper<T>(map: &mut HashMap<String, T>) {
    let mut tmp = Vec::with_capacity(map.len());
    for (key, val) in map.drain() {
        tmp.push((key.to_ascii_uppercase(), val));
    }
    for (key, val) in tmp {
        map.insert(key, val);
    }
}

К сожалению, у меня нет HashMap, но есть &mut serde_json::Map, и я хочу чтобы перевести все клавиши в верхний регистр. Нет .drain() метода. Вместо этого я мог бы использовать .into_iter(), но это дало бы мне только изменяемые ссылки на ключи и значения. Чтобы снова вставить их в карту, мне пришлось бы их клонировать, что снизило бы производительность.

Есть ли здесь способ обойти отсутствие метода .drain()?


person Anders    schedule 07.08.2020    source источник


Ответы (1)


Хороший инструмент в наборе инструментов программиста на Rust: std::mem::take. Это позволяет вам изменить &mut T на T, если тип реализует значение по умолчанию (если нет, но тип по-прежнему имеет фиктивное / дешевое значение, которое вы можете использовать, тогда _ 4_ - ваша функция выбора).

Применительно к вашему текущему варианту использования это дает:

use serde_json::{Map, Value};

fn keys_to_upper<T>(map: &mut Map<String, Value>) {
    *map = std::mem::take(map)
        .into_iter()
        .map(|(k, v)| (k.to_ascii_uppercase(), v))
        .collect();
}
person mcarton    schedule 07.08.2020