0
votes

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;

}
3
Your sort predicate must (1) have a different signature, as it's called with two arguments to be compared and (2) return a bool that indicates whether the first argument is to be considered "less" than the second. - lubgr
std::sort does not return anything. It sorts in place. When it returns idx_correlations will be sorted. If you want to keep that unsorted then you should make a copy first, like sorted = idx_correlations and pass iterators to sorted to sort. If you do fix that then prepare yourself for a really long error about the sort predicate that @lubgr mentioned. :) - Retired Ninja
sorted = std::sort(idx_correlations.begin(),... -- What was your intention with this code? This is not how std::sort works. - PaulMcKenzie
sorting pairs will have the following criteria: sort all pairs with respect to its first (x,y) the x here, and if equals it sorts by its second (x,y) the y here. - Nour Alhadi Mahmoud
@Cece -- It doesn't matter what types you're sorting -- they could be simple int, doubles, pairs, or Widgets -- it doesn't matter. The std::sort predicate takes two arguments of that type. You are given two values, and you're supposed to return true or false, depending on whether the first value should be placed before the second value. Maybe if you used modern C++ syntax using auto, things would be more understandable: std::sort(idx_correlations.begin(), idx.correlations.end(), [](auto& val1, auto& val2).... What auto is will depend on the types that the vector holds. - PaulMcKenzie

3 Answers

2
votes

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).

2
votes

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.

1
votes

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