使用“ C ++ 17或更高版本”对向量中的元素对求和的最“实用”方法?

时间:2019-05-31 15:09:54

标签: c++ c++17

我想为使用现代C ++从向量(第1和第2,第3和第4等)中收集连续元素对的最简洁和“功能性”方式提供一些建议。假设向量是任意的,但长度均匀。对于我要汇总的示例,我对每对元素进行求和,但这并不是主要问题。我应该补充说,我只会使用STL,而不会使用Boost。

在Python中,我可以通过迭代器将它们压缩为2元组

s = range(1,11)
print([(x + y) for x,y in zip(*[iter(s)] * 2)])

在Perl 5中,我可以使用

use List::Util qw/pairs sum/;
use feature 'say';
@s = 1 .. 10;
say sum @$_ foreach (pairs @s);

在Perl 6中,我可以一次将它们两个推入一个块中

my @s = 1 .. 10;
for @s -> $x, $y { say $x + $y; }

在R中,我可以将向量包装到2列数组中,并用

s <- 1:10
print(apply(matrix(s, ncol=2, byrow=TRUE), 1, sum))

我不太精通C ++,我的解决方案使用for(;;)。感觉太像C。

#include <iostream>
#include <vector>
#include <numeric>  // std::iota

int main() {
    std::vector<int> s(10);
    std::iota(s.begin(), s.end(), 1);
    for (auto p = s.cbegin(); p != s.cend(); p += 2)
        std::cout << (*p + *(p + 1)) << std::endl;
}

输出当然应该是

的某种变体
3
7
11
15
19

3 个答案:

答案 0 :(得分:8)

使用range-v3

for (auto v : view::iota(1, 11) | view::chunk(2)) {
    std::cout << v[0] + v[1] << '\n';
}   

请注意,chunk(2)不会为您提供编译时固定的大小视图,因此您不能这样做:

for (auto [x,y] : view::iota(1, 11) | view::chunk(2)) { ... }

答案 1 :(得分:1)

不使用range-v3,我就可以使用函数或lambda模板来做到这一点。我将在这里显示lambda版本。

#include <iostream>
#include <string>
#include <vector>

template<typename T>
auto lambda = [](const std::vector<T>& values, std::vector<T>& results) {
    std::vector<T> temp1, temp2;

    for ( std::size_t i = 0; i < values.size(); i++ ) {
        if ( i & 1 ) temp2.push_back(values[i]); // odd index
        else temp1.push_back(values[i]); // even index
    }

    for ( std::size_t i = 0; i < values.size() / 2; i++ )
        results.push_back(temp[i] + temp[2]);
};

int main() {
    std::vector<int> values{ 1,2,3,4,5,6 };
    for (auto i : values)
        std::cout << i << " ";
    std::cout << '\n';

    std::vector<int> results;
    lambda<int>(values, results);
    for (auto i : results)
        std::cout << i << " ";
    std::cout << '\n';

    std::vector<float> values2{ 1.1f, 2.2f, 3.3f, 4.4f };
    for (auto f : values2)
        std::cout << f << " ";
    std::cout << '\n';

    std::vector<float> results2;
    lambda<float>(values2, results2);
    for (auto f : results2)
        std::cout << f << " ";
    std::cout << '\n';

    std::vector<char> values3{ 'a', 'd' };
    for (auto c : values3)
        std::cout << c << " ";
    std::cout << '\n';

    std::vector<char> results3;
    lambda<char>(values3, results3);
    for (auto c : results3)
        std::cout << c << " ";
    std::cout << '\n';

    std::vector<std::string> values4{ "Hello", " ", "World", "!" };
    for (auto s : values4)
        std::cout << s;
    std::cout << '\n';

    std::vector<std::string> results4;
    lambda<std::string>(values4, results4);
    for (auto s : results4)
        std::cout << s;
    std::cout << '\n';

   return EXIT_SUCCESS;
}

输出

1 2 3 4 5 6
3 7 11
1.1 2.2 3.3 4.4
3.3 7.7
a d
┼
Hello World!
Hello World!

答案 2 :(得分:0)

冒着听起来我想变得聪明或烦人的风险,我说这就是答案:

print(sums(successive_pairs(range(1,11))));

现在,这些当然不是内置函数,因此您必须定义它们,但是我认为这不是一件坏事。该代码以功能性样式清楚地表达了您想要的内容。而且,每个功能的职责是完全分开的,易于测试的和可重用的。不必使用许多复杂的专门语法来以功能样式编写代码。