Rust: Itertools::GroupBy и владение
Я новичок в Rust, и у меня проблемы с пониманиемItertools::GroupBy
.
Вот пример, который я придумал для практикиGroupBy
. Дан массив целых чисел:
- Сгруппируйте его по значению чисел.
- Сохраняйте только группы с более чем 3 элементами.
- Верните вектор с ключами уцелевших групп.
Например, для данного массива
[1,1,1,1,-2,-2,-3,-3,-3,-3,4,4]
Я хочу вернуть вектор(1,-3)
, потому что 1 и 3 встречаются в массиве более трех раз.
вот моя попытка
let groups = [1, 1, 1, 1, -2, -2, -3, -3, -3, -3, 4, 4]
.into_iter()
.group_by(|element| *element)
.into_iter()
.filter(|(_, value)| value.count() > 3)
.map(|(key, _)| key)
.collect::<Vec<i32>>();
Вы можете попробовать это на игровой площадке Rust .
Строка с фильтром выдает ошибку: "невозможно выйти из того, что находится за общей ссылкой", где*value
перемещается из-за вызова методаcount()
.
Поэкспериментировав, я заметил, что могу исправить код, добавивmap
let groups = [1, 1, 1, 1, -2, -2, -3, -3, -3, -3, 4, 4]
.into_iter()
.group_by(|element| *element)
.into_iter()
.map(|(key, value)| (key, value.collect::<Vec<i32>>()))
.filter(|(_, value)| value.len() > 3)
.map(|(key, _)| key)
.collect::<Vec<i32>>();
Однако я хотел бы понять, почему моя первоначальная попытка не работает. Я понимаю, что это связано с заимствованием, но мои знания все еще слишком базовые.
1 ответ
не дает вам права собственности на элемент, он даже не дает вам изменчивости, он просто дает вам неизменяемые ссылки. Он ожидает, что вы сделаете вывод из неизменного ввода, следует ли что-то сохранить или удалить. Элементы просто обходят, ожидается, что они не изменятся, а будут просто выбраны.
Однако, чтобы понять, сколько значений в вашей группе, вы должны перебрать ее, потому что переменная является итератором. Однако вы не можете перебирать его, потому что по очевидным причинам это изменило быvalue
переменная, которая не разрешена внутри .
Однако есть решение:.filter_map()
метод сочетает в себе.filter()
и.map()
в одной операции и дает вам принадлежащий элемент и делать с ним, как вам угодно:
use itertools::Itertools;
fn main() {
let groups = [1, 1, 1, 1, -2, -2, -3, -3, -3, -3, 4, 4]
.into_iter()
.group_by(|element| *element)
.into_iter()
.filter_map(|(key, value)| (value.count() > 3).then_some(key))
.collect::<Vec<i32>>();
println!("{:?}", groups);
}
[1, -3]