0

So, i want to sort a map<string, vector<int>> by value in this kind of algorithm. There are 3 integers in the vector and i want to sort the map by the third value in the vector in the map in descending. If the third value is the same, sort by the second value descending, if the second value is the same then the first value.

Basically it goes like this:

P0001 10 100 100
P0002 0 0 200
P0003 1 100 100

After sorting:

P0002 0 0 200
P0001 10 100 100
P0003 1 100 100

My code:

#include <bits/stdc++.h>
using namespace std;
struct comp {
    template <typename T>
  
    // Comparator function
    bool operator()(const T& l,
                    const T& r) const
    {
        if(l.second[2] != r.second[2]){
            return l.second > r.second;
        }
        else{
            if(l.second[1] != r.second[1]){
                return l.second > r.second;
            }
            else{
                if(l.second[0] != r.second[0]){
                    return l.second > r.second;
                }
            }
        }
    }
};

void sort(map<string, vector<int>>& M)
{
  
    set<pair<string, vector<int>>, comp> S(M.begin(), M.end());
    for (auto& it : S) {
        cout << '\t' << it.first << '\t';
        for (int i = 0; i < 3; i++)
        {
            cout << it.second[i] << "\t";
        }
        cout << endl;
    }
}

int main(){
    int Q, N, input;
    string masuk, inputkey;
    map<string, vector<int>> peserta;
    vector<int> inputval;
    cin >> Q >> N >> masuk;
    for (int i = 0; i < Q; i++)
    {
        cin >> inputkey;
        for (int i = 0; i < 3; i++)
        {
            cin >> input;
            inputval.push_back(input);
        }
        peserta.insert(pair<string, vector<int>>(inputkey, inputval));
        inputval.clear();
    }

    sort(peserta);
    

    return 0;
}

I have read

https://www.geeksforgeeks.org/sorting-a-map-by-value-in-c-stl/
https://www.geeksforgeeks.org/map-of-vectors-in-c-stl-with-examples/
map of vectors in STL?

So far the inserting of the value works, only the sorting gone wrong.

rawrex
  • 4,044
  • 2
  • 8
  • 24
  • Please take a look at [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) in the meantime. – rawrex Jun 28 '21 at 07:04
  • please, in competitive programming i think it's fine to use that, i've seen numerous competitive programmer does that, look at https://www.youtube.com/channel/UCBr_Fu6q9iHYQCh13jmpbrg – HD-coders64 Jun 28 '21 at 07:06
  • 2
    Well it is *used* in competitive programming. Yet you should not use it in daily programming, and **never** when asking a question on SO. Because it clutters the main namespace with tons of useless names, and could introduce nasty bugs that we really do not want to chase. – Serge Ballesta Jun 28 '21 at 07:16
  • 1
    `#include ` is never good. Yes, many people use it, but that doesn't make it good. The most important part is, that it makes your problem non-reproducible for people that don't have access to a compiler which supports this non-standard header. And especially in combination with `using namespace std;` it has a tendency of causing strange errors. And this is seen regularly on SO. – Lukas-T Jun 28 '21 at 07:31
  • 1
    Secondly: The `if`-`else`-chain in `comp::operator()` seems useless. It returns `return l.second > r.second;` in every case. – Lukas-T Jun 28 '21 at 07:33

2 Answers2

3

You can't sort a map like that, because it sorts its keys automatically and doesn't allow you to break order. What you can do is create a wrapper class around your string and vector, define a custom comparison operator for it and use std::set instead. You won't be able to get elements by their keys, though. If you want both getting by key and sorting, you may read about Boost.MultiIndex, or combine multiple containers for your task.

0

As already said in another answer, a map is only sorted by its key.

If you don't use boost and you only need the alternative sorting temporarily, you can get away with an extra map std::multi_map<int, std::map<string, vector<int>>::iterator> where you put all iterators to elements, based on a new key (third value in vector). Mind you, this new map is only valid as long as the original map doesn't change. If this is not good enough, you need to put the two map in an extra class to do the bookkeeping and so you're making a Boost.MultiIndex.

stefaanv
  • 14,072
  • 2
  • 31
  • 53