【问题标题】:Iterating over a column of a multidimensional array with std::count_if()?使用 std::count_if() 遍历多维数组的列?
【发布时间】:2020-12-24 01:30:04
【问题描述】:

我有一个 double 类型的多维数组 (double someArray[10][20])。我愿意:

a) 使用 std::count_if() 遍历该数组的单个列,返回大于某个数字的值的数量

b) 还要求该数字的行索引在一定范围内。

我知道使用std::count_if 的基础知识(例如,我知道如何迭代某些向量并返回大于/小于/等于某个值的值),但我不确定如何在多维数组的列上执行此操作,或者如何检查元素的索引是否也满足某些条件。

【问题讨论】:

  • 能否至少给我们展示一下多维数组的定义,并告诉我们您要检查哪一列?
  • @πάνταῥεῖ 数组是 10 x 20。我最终会多次调用 std::count_if(),检查某个条件选择的列。所以,我可能想检查第 3 列的值是否大于 7,行索引介于 2 和 12 之间。这只是一个例子。它或多或少取决于外部条件和用户输入。
  • 所以你有一个std::array<std::aray<double,20>,10>Edit您的问题,而不是让我们猜测。
  • @πάνταῥεῖ 我有双倍 myArray[10][20]
  • See if you can use this answer as a starting point。二维数组中的数据是连续的,因此您可以使用开始和结束迭代器轻松地将任何算法应用于数据,即开始:&somearray[0][0],结束:&somearray[9][20]。步数只是20。所以你只需要做一个简单的计算就可以算出列的起始地址。

标签: c++ arrays algorithm stl


【解决方案1】:

分而治之。

  • 使用count_if 遍历多维数组的单列,检查该行的索引是否在特定范围内。

将问题分解成更小的部分,直到它们小到可以解决为止。

  • 使用count_if
  • 遍历多维数组的单列
  • 检查行的索引是否在一定范围内

嗯...第一个任务看起来可行。也许是最后一个。回到部门。

  • 使用std::count_if
  • 迭代:
    • 在数组上
    • 但它是多维的
    • 只有一列很重要
  • 检查行的索引是否在一定范围内

在给定std::beginstd::end 的情况下,遍历数组并不难。多维方面看起来很可怕,所以让我们拭目以待,看看我们能走多远。现在,只需将“迭代数组”插入“使用count_if”即可。

std::count_if(std::begin(someArray), std::end(someArray), [](auto & element)
    { return ???; });

嗯……element这个名字不准确吧?当std::begin 应用于double [][20] 时,只消耗一个维度。取消引用的结果不是double而是double [20],所以row会是一个更准确的名称。

std::count_if(std::begin(someArray), std::end(someArray), [](auto & row)
    { return ???; });

多维方面可能已经处理好了。我们可以只关注一列吗?假设名为 column 的变量是所需的列索引,target 可以是问题描述中的“某个数字”。

std::count_if(std::begin(someArray), std::end(someArray), [column, target](auto & row)
    { return row[column] > target; });

这样就可以将行索引限制在某个范围内。也就是说,迭代受限范围而不是整个数组。看起来像是 std::nextstd::prev 的工作。我们只需要另外两个变量来给我们范围;让我们使用fromto

// Check only the desired rows
auto start = std::next(std::begin(someArray), from);
auto stop =  std::prev(std::end(someArray), 9 - to);

return std::count_if(start, stop, [column, target](auto & row)
    { return row[column] > target; });

(我不喜欢那个神奇的数字9。最好是ROWS-1,假设已经声明了合适的常量,这样数组的声明就可以变成double someArray[ROWS][COLS]。)

【讨论】:

    【解决方案2】:

    如果您愿意使用boost::range,您可以使用count_if 与步数。

    这会起作用的原因是,无论维数如何,数组都会将其数据存储在连续的内存中,因此随机访问迭代将与一维数组一样工作。

    因此,目标是找出起始列(简单),而不是像使用“正常”std::count_if 那样一次迭代一个元素,而是要迭代(在你的情况下)@987654324 @ 元素,因为迭代那么多会将您带到您感兴趣的列的下一行。

    对于M x N 大小的二维数组,用于 STL 算法函数的起始地址和结束地址为:

    start: &array2D[0][0]
    end (one item passed the end): &array[M-1][N]
    

    鉴于此信息,这里是使用boost 的示例:

    #include <boost/range/adaptor/strided.hpp>
    #include <boost/range/algorithm/copy.hpp>
    #include <boost/assign.hpp>
    #include <boost/range/algorithm.hpp>
    #include <algorithm>
    #include <iostream>
    #include <numeric>
    
    int main()
    {
        using namespace boost::adaptors;
        using namespace boost::assign;
    
        // declare and fill in the array with numbers starting from 0
        double someArray[10][20];
        std::iota(&someArray[0][0], &someArray[9][20], 0.0);
    
        // let's get the address of the start of the third column
        const double* startAddr = &someArray[0][2];  
    
       // here is the address of the end of the 2-dimensional array
        const double* endAddr = &someArray[9][20];  // add up the third column
    
        // create a SinglePass range consisting of the starting and ending address
        // plus the stride count
        auto str = std::make_pair(startAddr, endAddr) | strided(20);
    
        // count how many items in the third column are less than 60
        auto result = boost::range::count_if(str, [&](double val) { return val < 60; });
        std::cout << result;
    }
    

    输出:

    3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-16
      • 2016-09-23
      • 2015-09-26
      • 1970-01-01
      相关资源
      最近更新 更多