Код для сумм в векторе

Я отправил этот код в ответ ранее сегодня, но подумал, что стоит посмотреть, сможет ли кто-нибудь предложить дальнейшие улучшения:

#include <numeric>
#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>

template <class InIt, class OutIt>
OutIt adjacent_sum(InIt begin, InIt end, OutIt result) { 
    ++begin;     
    while (begin != end) {
        *result = *begin + *(begin-1);
        ++result;
        ++begin;
    }
    return result;
}

int main() { 
    std::vector<int> inputs { 1, 2, 3, 4, 5, 10, 9, 8, 7, 6};

    adjacent_sum(inputs.begin(), inputs.end(), 
        std::ostream_iterator<int>(std::cout, "\t"));

    std::cout << "\n";

    std::transform(inputs.begin(), inputs.begin()+inputs.size()/2, 
        inputs.rbegin(), 
        std::ostream_iterator<int>(std::cout, "\t"), 
        std::plus<int>());
}

Здесь я разместил фиксированный вход в вектор inputs. Цель состоит в том, чтобы сначала произвести суммы смежных элементов во входе, а во втором - сумму первого элемента, добавленного к последнему элементу, второй элемент добавлен ко второму к последнему и т. Д.

11 голосов | спросил Jerry Coffin 18 J0000006Europe/Moscow 2014, 04:51:45

3 ответа


12

Вы делаете предположение о итераторах произвольного доступа.
Было бы неплохо иметь возможность делать это с любым итератором (включая итератор ввода)

template <class InIt, class OutIt>
OutIt adjacent_sum(InIt begin, InIt end, OutIt result)
{ 
    if (begin == end)
    {     return result;    // From @Corbin
    }

    auto  last = (*begin);  // Get the value now before incrementing the iterator.
    ++begin;     
    while (begin != end)
    {
        auto next = (*begin);
        *result   = next + last;
        last      = next;

        ++result;
        ++begin;
    }
    return result;
}

Теперь работает следующее:

adjacent_sum(std::istream_iterator<int>(std::cin), std::istream_iterator<int>(), 
             std::ostream_iterator<int>(std::cout, "\t"));
ответил Martin York 18 J0000006Europe/Moscow 2014, 22:48:04
8

Вероятно, вы знаете об этих ограничениях, и они подразумевают предварительные условия для adjacent_sum, но только ради этого будучи CodeReview, у меня есть две критики в отношении adjacent_sum, один довольно большой и другой незначительный.

Явная проверка пустых диапазонов должна выполняться в adjacent_list. Если begin == end при вызове adjacent_sum, ++begin почти наверняка не будет равно end, и это что приведет к очень неприятному циклу.

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

ответил Corbin 18 J0000006Europe/Moscow 2014, 08:02:27
3

Я просто использовал бы std::adjacent_difference из <numeric>. Он предназначен для приема пользовательских двоичных операций, таких как plus<> и multiplies<> из библиотеки <functional>.

std::adjacent_difference(inputs.begin(), inputs.end(), std::ostream_iterator<int>(std::cout, " "), std::plus<int>());

Если вы собираетесь использовать свою собственную смежную сумму, включите обработку для пустых /одиночных списков элементов.

template <class InIt, class OutIt>
OutIt adjacent_sum(InIt begin, InIt end, OutIt result) {
    if (begin == end)    // Corbin
        return result;

    auto last = *begin;  // Loki
    for (*result = last; ++begin != end;) { // Me
        auto next = *begin;
        *++result = last + next;
        last = std::move(next);
    }

    return result;
}
ответил Snowhawk 20 J0000006Europe/Moscow 2014, 13:36:25

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132