Почему Iterator::take_while вступает во владение итератором?
Я нахожу странным, что Iterator::take_while
вступает во владение итератором. Это кажется полезной возможностью, чтобы иметь возможность взять первые элементы x, которые удовлетворяют некоторой функции, но все же оставляют остальные элементы доступными в исходном итераторе.
Я понимаю, что это несовместимо с ленивой реализацией take_while
, но все еще чувствует себя полезным. Было ли это просто признано недостаточно полезным для включения в стандартную библиотеку, или есть какая-то другая проблема, которую я не вижу?
2 ответа
Все адаптеры итераторов берут исходный итератор по значению ради эффективности. Кроме того, владение оригинальным итератором позволяет избежать необходимости иметь время жизни, когда в этом нет необходимости.
Если вы хотите сохранить доступ к исходному итератору, вы можете использовать by_ref
, Это вводит один уровень косвенности, но программист выбирает дополнительную работу, когда требуется эта функция:
fn main() {
let v = [1, 2, 3, 4, 5, 6, 7, 8];
let mut i1 = v.iter();
for z in i1.by_ref().take_while(|&&v| v < 4) {
// ^^^^^^^^^
println!("Take While: {}", z);
}
for z in i1 {
println!("Rest: {}", z);
}
}
Имеет выход
Take While: 1
Take While: 2
Take While: 3
Rest: 5
Rest: 6
Rest: 7
Rest: 8
Вы заметили, что 4
скучал? Это потому, что однажды take_while
выбирает значение и решает не использовать его, ему некуда "вернуть его". Чтобы вернуть его обратно, потребуется больше памяти и медлительность, чем всегда требуется.
Я использовал контейнер itertools для обработки подобных случаев, особенно take_while_ref
,
Если это становится слишком сложным, возможно, мы использовали не тот инструмент.
Обратите внимание, что здесь присутствует 4:
fn main() {
let v = [1, 2, 3, 4, 5, 6, 7, 8];
let mut i1 = v.iter().peekable();
loop {
match i1.peek() {
Some(n) => {
if n < &&4 {
println!("Take While: {}", n);
} else {
println!("Rest: {}", n);
}
}
None => return,
}
i1.next();
}
}
Take While: 1
Take While: 2
Take While: 3
Rest: 4
Rest: 5
Rest: 6
Rest: 7
Rest: 8
Да, ОП просил
take_while
и решение Шепмастера превосходно.