Получить состояние в Scan () итератор? - PullRequest
0 голосов
/ 05 марта 2020

Чтобы получить частичные суммы последовательности целых чисел, я могу использовать scan() на итераторе следующим образом:

let partial: Box<[u32]> =
    list
    .iter()
    .scan(0, |st, elem| {
        let ret = *st;
        *st += elem;
        Some(ret)
    })
    .collect();

Приведенный выше код работает хорошо, но я пытаюсь изменить его на дайте мне также общую сумму.

Что-то вроде:

let (partial, total): (Box<[u32]>, u32) =
    list
    .iter()
    .scan(0, |st, elem| {
        // TODO
    })
    .collect();

Похоже, мне просто нужно получить конечное значение st, и итератор должен уже знать, что это ценность. Однако я не могу найти способ извлечь это значение, если не выполнять вторую итерацию по всей последовательности (например, с помощью fold()).

Есть ли способ найти частичные суммы и общая сумма за один проход?

Ответы [ 2 ]

2 голосов
/ 05 марта 2020

Включите общую сумму в scan, но затем выделите последнее значение.

use std::iter;

fn main() {
    let list = vec![1, 2, 3, 4];

    // Add zero at the start to emulate what you had before
    let partial: Box<[u32]> = iter::once(0)
        .chain(list.iter().scan(0, |st, elem| {
            *st += elem;
            Some(*st)
        }))
        .collect();
    // unwrap since with the added zero, the slice will always be non-empty
    let (total, partial) = partial.split_last().unwrap();

    println!("partial sums: {:?}", partial);
    println!("total sum: {}", total);
}

(детская площадка)


Или используя successors():

fn main() {
    use std::iter::successors;

    let list = vec![1, 2, 3, 4];

    let mut iter = list.iter();
    let partial: Vec<_> = successors(Some(0), |n| iter.next().map(|i| n + i)).collect();
    // unwrap since with the added zero, the slice will always be non-empty
    let (total, partial) = partial.split_last().unwrap();

    assert_eq!(partial, &[0, 1, 3, 6]);
    assert_eq!(total, &10);
}

(детская площадка)

0 голосов
/ 05 марта 2020

Вы должны решить, что вы хотите сделать в замыкании.

Когда оно стоит в вашем коде, вы помните ret = *st, которое является значением аккумулятора до добавления, и вы вернетесь Some(ret). Таким образом, первый элемент, который вы получаете в результате, в настоящее время 0.

Если вы хотите получить значение после сумм, вы должны просто вернуть Some(*st), то есть значение обновленного аккумулятора после дополнение.

...