简体   繁体   English

使用 std::count_if() 迭代多维数组的一列?

[英]Iterating over a column of a multidimensional array with std::count_if()?

I have a multidimensional array of type double ( double someArray[10][20] ).我有一个 double 类型的多维数组( double someArray[10][20] )。 I'd like to:我想:

a) use std::count_if() to iterate over a single column of that array, returning the number of values greater than some number a) 使用std::count_if()迭代该数组的单列,返回大于某个数字的值的数量

b) also require that the row index of that number is within a certain range. b) 还要求该数字的行索引在一定范围内。

I know the basics of using std::count_if (ie I know how to iterate over, say, some vector and return values greater than/less than/equal to some value, for example), but I'm not sure how to do this over a column of a multidimensional array, or how to check that the index of the element also satisfies some condition.我知道使用std::count_if的基础知识(例如,我知道如何迭代某些向量并返回大于/小于/等于某个值的值),但我不知道该怎么做this 在多维数组的一列上,或者如何检查元素的索引是否也满足某些条件。

If you are willing to use boost::range , you can use the count_if with a stride count.如果您愿意使用boost::range ,则可以使用带有步幅计数的count_if

The reason why this will work is that an array, regardless of the number of dimensions, will store its data in contiguous memory, thus random-access iteration will work exactly as it would a one-dimensional array.这将起作用的原因是,无论维数如何,数组都将其数据存储在连续内存中,因此随机访问迭代将与一维数组完全一样工作。

Thus the goal is to figure out the starting column (easy), and instead of iterating one element at a time forward as you would with the "normal" std::count_if , you want to iterate (in your case) 20 elements, since iterating that many will take you to the next row of the column you're interested in.因此,目标是找出起始列(简单),而不是像使用“正常” std::count_if那样一次迭代一个元素,而是要迭代(在您的情况下) 20元素,因为迭代许多将带您到您感兴趣的列的下一行。

For a 2D array of M x N size, the starting and ending addresses you would use for the STL algorithm functions would be:对于M x N大小的二维数组,用于 STL 算法函数的起始地址和结束地址将是:

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

Given this information, here is an example using boost :鉴于此信息,以下是使用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;
}

Output:输出:

3

Divide and conquer.分而治之。

  • Use count_if to iterate over a single column of a multidimensional array, checking that the index of the row is within a certain range.使用count_if迭代多维数组的单列,检查该行的索引是否在一定范围内。

Break the problem into smaller pieces, until they are small enough to solve.将问题分解成更小的部分,直到它们小到可以解决为止。

  • Use count_if使用count_if
  • iterate over a single column of a multidimensional array迭代多维数组的单列
  • checking that the index of the row is within a certain range检查行的索引是否在一定范围内

Hmm... that first task looks doable.嗯……第一个任务看起来可行。 Maybe the last.也许是最后。 Back to division.回到分区。

  • Use std::count_if使用std::count_if
  • iterate:迭代:
    • over an array在一个数组上
    • but it's multidimensional但它是多维的
    • only one column matters只有一栏重要
  • checking that the index of the row is within a certain range检查行的索引是否在一定范围内

Iterating over an array is not hard, given std::begin and std::end .鉴于std::beginstd::end ,迭代数组并不难。 The multidimensional aspect looks scary, so let's wait on that and see how far we can get.多维方面看起来很可怕,所以让我们拭目以待,看看我们能走多远。 For now, just plug "iterate over an array" into "use count_if ".现在,只需将“迭代数组”插入“使用count_if ”。

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

Hmm... the name element is not accurate is it?嗯...名称element不准确是吗? When std::begin is applied to double [][20] , only one dimension is consumed.std::begin应用于double [][20] ,只消耗一维。 The result of de-referencing is not double but double [20] , so row would be a more accurate name.取消引用的结果不是double而是double [20] ,因此row将是一个更准确的名称。

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

The multidimensional aspect might have just taken care of itself.多维方面可能刚刚照顾好自己。 Can we focus on just one column?我们可以只关注一栏吗? Let's assume a variable named column is the desired column index, and target can be the "some number" from the problem description.让我们假设一个名为column的变量是所需的列索引,而target可以是问题描述中的“某个数字”。

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

So that leaves restricting the row index to a certain range.这样就可以将行索引限制在某个范围内。 That is, iterate over the restricted range instead of over the entire array.也就是说,迭代受限范围而不是整个数组。 Looks like a job for std::next and std::prev .看起来像是std::nextstd::prev We'll just need two more variables to give us the range;我们只需要另外两个变量来为我们提供范围; let's use from and to .让我们使用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; });

(I don't like that magic number 9 . Better would be ROWS-1 , assuming suitable constants have been declared so that the array's declaration can become double someArray[ROWS][COLS] .) (我不喜欢那个神奇的数字9 。最好是ROWS-1 ,假设已经声明了合适的常量,以便数组的声明可以变成double someArray[ROWS][COLS] 。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM