Cece
Cece

Reputation: 45

std::vector<std::pair<int, float>> and void error

I'd like to sort m_correlationValues in descending order and get ids of the sorted list. I've got this error. I'll appreciate your help. no match for 'operator=' (operand types are 'std::vector<std::pair<int, float> >' and 'void') return idx_correlation.second; });

  void MatrixCanvas::SortMatrix()
  {
    int naxes = (int) m_correlationData.size();
    std::vector<std::pair<int,float>> idx_correlations;
    std::vector<std::pair<int,float>> sorted;
    std::vector<int> idxs(naxes);

    for(int idx =0; idx<naxes;idx++){
        idx_correlations[idx] = std::make_pair(idx, m_correlationValues[chosen_row_id][idx]);}

        // Wrong
        sorted = std::sort(idx_correlations.begin(),
                            idx_correlations.end(),
                            [](std::pair<int,float> &idx_correlation){
                            return idx_correlation.second; });

    // this will contain the order:
    for(int i =0; i<naxes;i++)
        idxs[i] = sorted[i].first;

}

Upvotes: 0

Views: 675

Answers (3)

Chris Uzdavinis
Chris Uzdavinis

Reputation: 6131

You have two problems:

  1. sort does not return a copy of the sorted range. It modifies the range provided. If you want the original to be left alone, make a copy of it first and then sort it.

  2. std::sort's third argument is a comparator between two values, which has the meaning of "less than". That is, "does a come before b?" For keeping the line short, I replaced your pair<...> type with auto in the lambda, but it'll be deduced to "whatever type of thing" is being sorted.

Note, if you want decreasing, just change < to > in the lambda when it compares the two elements.

Possible fix:

    auto sorted = idx_correlations; // full copy
    std::sort(sorted.begin(),
              sorted.end(),
              [](auto const & left, auto const & right) {
                   return left.first < right.first; });

After that, sorted will be a sorted vector and idx_correlations will be left unchanged. Of course, if you don't mind modifying your original collection, there's no need to make this copy (and you can take begin/end of idx_correlations.

Upvotes: 2

Marek R
Marek R

Reputation: 37697

The other answers covered proper use of std::sort, I wish to show C++20 std::rannges::sort which have projection functionality what is close to thing you've tried to do:

    std::vector<std::pair<int, float>> idx_correlations;
     .....
    auto sorted = idx_correlations;
    std::ranges::sort(sorted, std::greater{}, &std::pair<int, float>::second);

https://godbolt.org/z/4rzzqW9Gx

Upvotes: 1

Nour Alhadi Mahmoud
Nour Alhadi Mahmoud

Reputation: 453

So the main issue I can see in your code, is that you're expecting the std::sort to return the sorted vector, and this is NOT how it works.

https://en.cppreference.com/w/cpp/algorithm/sort

The solution in your case is to get the sorted vector out of the original vector, ie. sorted = idx_correlations then sort the new vector.

sorted = idx_correlations;
std::sort( sorted.begin(), sorted.end(), your_comparator... );

This will do the trick while also maintaining the original vector.

Update: another issue is that your comparator will have TWO arguments not one (two elements to compare for the sort).

Upvotes: 2

Related Questions