Я написал фрагмент кода для использования HashMap<String, Vec<&String>> в качестве основной структуры данных, и, наконец, я хочу вернуть собранный Vec<Vec<String>>, Я могу заархивировать его с помощью цикла for, есть ли способ сделать это с помощью чистого итератора? (Я пробовал несколько раз, но получил массу запутанных ошибок компилятора)
pub fn group_anagrams(strs: Vec<String>) -> Vec<Vec<String>> {
let mut map: HashMap<String, Vec<&String>> = HashMap::new();
for s in &strs {
let mut key = s.clone();
unsafe {
key.as_bytes_mut().sort();
}
(*map.entry(key).or_insert(vec![])).push(s);
}
let mut ans: Vec<Vec<String>> = Vec::new();
// I don't like these 2 lines
for v in map.values() {
ans.push(v.iter().cloned().cloned().collect::<Vec<String>>())
}
ans
}
Я также пробовал с этим кодом:
pub fn group_anagrams(strs: Vec<String>) -> Vec<Vec<String>> {
let mut map: HashMap<String, Vec<String>> = HashMap::new();
for s in strs {
let mut key = s.clone();
unsafe {
key.as_bytes_mut().sort();
}
(*map.entry(key).or_insert(vec![])).push(s);
}
map.values().cloned().collect::<Vec<Vec<String>>>()
}
В последней строке я хочу переместить все значения из hashmap в результирующий вектор, но также не удалось из-за ошибки времени жизни (тогда я отказался от клонированного вектора), мне интересно, как это сделать.
1 ответ
unsafe {
key.as_bytes_mut().sort();
}
Это работает, пока вы работаете в Ascii, но будет иметь неопределенное поведение, если в строке есть какой-либо юникод.
(*map.entry(key).or_insert(vec![])).push(s);
Вам не нужно разыменование *, вызов метода позаботится об этом автоматически.
Немного сложно ответить на ваш главный вопрос, так как я не знаю, что именно вы пробовали и почему это не сработало.
Довольно прямой перевод того, что вы написали, в синтаксис итератора работает:
map.values()
.map(|v| v.iter().cloned().cloned().collect::<Vec<String>>())
.collect()
Однако я бы посоветовал сделать что-то более похожее на ваш второй блок кода и избегать клонирования строк:
map.values().cloned().collect::<Vec<Vec<String>>>()
Я бы сделал это:
map.into_iter()
.map(|(_key, values)| values)
.collect()
Используя итератор, мы избегаем клонирования векторов.
В качестве альтернативы возьмите строки как входные по ссылке и верните их по ссылке:
pub fn group_anagrams(strs: &[String]) -> Vec<Vec<&String>> {
let mut map: HashMap<String, Vec<&String>> = HashMap::new();
for s in strs {
let mut key = s.clone();
unsafe {
key.as_bytes_mut().sort();
}
(*map.entry(key).or_insert(vec![])).push(s);
}
map.into_iter()
.map(|(_key, values)| values)
.collect()
}

Большое спасибо!
— доисторический пингвин