rebatoma
rebatoma

Reputation: 742

c++ method to order a matrix by elements in a column (the same of sortrows in MATLAB)

I'm looking for a c++ method that is able to order the rows of a matrix by a decreasing order of the values in a specific column.

For example, if this is my input:

matrix = [1,2,3;
          2,4,1;
          0,5,2]

the call of the method(matrix,3) should provide the following output:

outputMatrix = [1,2,3;
                0,5,2;
                2,4,1]

In MATLAB this can be done by the calling of the function:

outputMatrix = sortrows(matrix,3).

What about c++? (In both cases, 3 is the index of the column).

Moreover in the script I'm working, the matrix is defined as a vector of vector: std::vector<std::vector<double> > matrix

[EDIT] I add another example:

input = [4,5,6;
         0,2,8;
         1,2,3;
         6,7,9]

outputMatrix = sortrows(input,2); Column 2, ordered, is: 9,8,6,3; so I have to order the rows and copy the elements of the first two columns (respectively 0 and 1).

 outputMatrix = [6,7,9;
                 0,2,8;
                 4,5,6;
                 1,2,3]

I report here the method I wrote to do this, but I don't know if this is a fast way:

std::vector<std::vector<double> > sortrows(std::vector<std::vector<double> > matrix,int col){
    int length = matrix[col].size();
    std::vector<std::vector<double> > output(3,std::vector<double>(length*length));
    output[col] = matrix[col];
    std::sort(output[col].begin(),output[col].end(),std::greater<double>());
    for (int i = 0; i < length*length;i++){
        int index = 0;
        while(output[col][i]!=matrix[col][index]){index++;}
        output[0][i]=matrix[0][index];
        output[1][i]=matrix[1][index];
        matrix[2][index] = -1;
    }
    return output;
}

Upvotes: 3

Views: 9793

Answers (2)

Muhammet Dabak
Muhammet Dabak

Reputation: 66

template<typename T>
void SortRows(std::vector<std::vector<T>>& inputVector,int col)
{
    bool stay{true};
    for (int ii = 0; ii< inputVector.size();ii++)
    {
        if(stay)
        {
            stay = false;
            for(int jj=0;jj<inputVector.size()-1;jj++)
            {
                if(inputVector[jj][col] < inputVector[jj+1][col])
                {
                    inputVector[jj].swap(inputVector[jj+1]);
                    stay = true;
                }
            }
        }
        else
        {
            break;
        }
    }
}

This is a bubble sort algorithm that solves your problem.

Notice that this algorithm changes the input with descending order due to '<' sign, you can use '>' for ascending order.

If you have any hesitation, please ask again.

Upvotes: 0

Xiaotian Pei
Xiaotian Pei

Reputation: 3260

Something like following (in C++11), sort the matrix rows based on a specific column

void sortrows(std::vector<std::vector<double>>& matrix, int col) {    
    std::sort(matrix.begin(),
              matrix.end(),
              [col](const std::vector<double>& lhs, const std::vector<double>& rhs) {
                  return lhs[col] > rhs[col];
              });
}

Also notice, this code changes the original matrix rather than returning a new matrix.

non C++11 version:

class Compare {
public:
    Compare(int col) : col_(col) {}
    bool operator()(std::vector<double>& lhs, std::vector<double>& rhs) {
        return lhs[col_] > rhs[col_];
    }
private:
    int col_; 
};

void sortrows(std::vector<std::vector<double>>& matrix, int col) {    
    std::sort(matrix.begin(), matrix.end(), Compare(col));
}

Upvotes: 6

Related Questions