如何在 C++ 向量(本征)中获得最大的 n 个值?

How to get largest n values in c++ vector (Eigen)?

我在 C++ 中有一个相当大的特征矩阵,但现在我希望在每一列中只有 6 个不等于 0 的值。 因此,我想将所有值设置为 0,最大的 6 除外。 我不知道我该怎么做,谁能帮帮我?

//std
#include <iostream>
#include <vector>
#include <numeric>
//eigen
#include <Eigen/Dense>
 
using namespace std;
 
int main()
{
  Eigen::MatrixXf m(4,4);
  m <<  1, 2, 3, 4,
        5, 6, 7, 8,
        9,10,11,12,
       13,14,15,16;
       
  // Take the 2nd column
  auto col1 = m.col(1);

  // Generate a sequence of indices for each value in the column
  std::vector<size_t> idx(m.rows(), 0);
  std::iota(idx.begin(), idx.end(), 0);

  // Sort the indices according to their respective value
  std::sort(idx.begin(), idx.end(), [&col1](auto& lhv, auto& rhv){ return col1(lhv) < col1(rhv); });

  // Ignore the last 2 (so, the 2 biggest). Or 6 in your case.
  idx.resize(idx.size() - 2);

  // Set the rest to 0
  for(auto id: idx) {
      col1(id) = 0;
  }

  cout << m << endl; 
  // Output : 
  // 1  0  3  4
  // 5  0  7  8
  // 9  10 11 12
  // 13 14 15 16
}

我会那样做。

void trimMatrix( Eigen::MatrixXd& matrix )
{
    constexpr size_t elementsToKeep = 6;

    std::vector<uint32_t> vec;
    vec.reserve( matrix.cols() );

    for( ptrdiff_t col = 0; col < matrix.cols(); col++ )
    {
        // Collect non-zero elements from a column of the matrix
        vec.clear();
        // BTW, when the matrix is sparse and column major, Eigen has a faster way to iterate over non-zero elements.
        for( ptrdiff_t r = 0; r < matrix.rows(); r++ )
        {
            double e = matrix( r, col );
            if( e != 0.0 )
                vec.push_back( (uint32_t)r );
        }

        if( vec.size() <= elementsToKeep )
            continue;   // Not enough non zero elements, nothing to do for the column.

        // Partition the vector into 2 sorted pieces.
        // Standard library has an algorithm for such partition, faster than sorting.
        // BTW the code is only good for column major matrices.
        // For row major ones RAM access pattern is bad, need another way.
        std::nth_element( vec.begin(), vec.begin() + elementsToKeep, vec.end(), [&matrix, col]( uint32_t a, uint32_t b )
            {
                const double e1 = matrix( a, col );
                const double e2 = matrix( b, col );
                // Using `>` for order because we want top N elements before elementsToKeep
                return std::abs( e1 ) > std::abs( e2 );
            } );

        // Zero out elements outside of the top N
        for( auto it = vec.begin() + elementsToKeep; it != vec.end(); it++ )
            matrix( *it, col ) = 0.0;
    }
}