Вы действительно можете использовать group_by
для этого, но вы, возможно, этого не хотите.Вот что я, вероятно, вместо этого написал бы:
fn consecutive_slices(data: &[i64]) -> Vec<&[i64]> {
let mut slice_start = 0;
let mut result = Vec::new();
for i in 1..data.len() {
if data[i - 1] + 1 != data[i] {
result.push(&data[slice_start..i]);
slice_start = i;
}
}
if slice_start > 0 {
result.push(&data[slice_start..]);
}
result
}
Это в принципе похоже на ответ eXodiquas, но вместо накопления Vec<Vec<i64>>
я использую индексы для накопления Vec
ссылок на срезы, которыеобратитесь к исходным данным.( Этот вопрос объясняет, почему я заставил consecutive_slices
взять &[T]
.)
Также можно сделать то же самое без выделения Vec
, возвращая итератор;Тем не менее, мне нравится выше версия лучше.Вот версия с нулевым распределением, которую я придумал:
fn consecutive_slices(data: &[i64]) -> impl Iterator<Item = &[i64]> {
let mut slice_start = 0;
(1..data.len() + 1).flat_map(move |i| {
if i == data.len() || data[i - 1] + 1 != data[i] {
let begin = slice_start;
slice_start = i;
Some(&data[begin..i])
} else {
None
}
})
}
Она не так удобна для чтения, как цикл for
, но ей не нужно выделять Vec
для возвращаемого значения, так чтоверсия более гибкая.
Больше для развлечения, чем потому, что я думаю, что это хорошая идея, вот «более функциональная» версия, использующая group_by
:
use itertools::Itertools;
fn consecutive_slices(data: &[i64]) -> Vec<Vec<i64>> {
(&(0..data.len()).group_by(|&i| data[i] as usize - i))
.into_iter()
.map(|(_, group)| group.map(|i| data[i]).collect())
.collect()
}
Идея состоит в том,сделать ключевую функцию для group_by
, которая принимает разницу между каждым элементом и его индексом в срезе.Последовательные элементы будут иметь одинаковый ключ, потому что индексы увеличиваются на 1 каждый раз.Одна из причин, по которой я говорю, что это не очень хорошая идея, заключается в том, что довольно сложно получить фрагменты исходной структуры данных;вам почти нужно создать Vec<Vec<i64>>
(отсюда два collect
s).Другая причина в том, что мне трудно читать.Если вложенная Vec
- это то, что вам действительно нужно, ответ eXodiquas , вероятно, является лучшей отправной точкой.