How to make a map sort by value C++

后端 未结 5 1221
情话喂你
情话喂你 2021-01-29 08:08

I was trying to make a map sort by value using a custom comparator but I couldn\'t figure out why I kept getting the error of \"no matching call to compareByVal\"

Here\'

相关标签:
5条回答
  • 2021-01-29 08:18

    The first, simple problem is

    struct compareByVal {
      bool operator[](const std::pair<int,int> & a, const std::pair<int,int> & b)
        return a.second < b.second;
    }
    

    should be

    struct compareByVal {
      bool operator()(const std::pair<int,int> & a, const std::pair<int,int> & b) const {
        return a.second < b.second;
      }
    };
    

    The second, serious problem is the signature of the compare is wrong. It should be

    struct compareByVal {
      bool operator()(const int leftKey, const int rightKey) const;
    }
    

    You can't access the value in the compare function. There is no (simple) way to sort a map by value.

    0 讨论(0)
  • 2021-01-29 08:29

    Well, first, the reason you're getting the error: "no matching call to compareByVal" is because map's comparator works only with the keys. So the comparator should like:

    struct compareByVal {
      template <typename T>
      bool operator()(const T& a, const T& b) const
        return a < b;
    }
    

    Coming on to what you want to achieve, I see two ways of doing so:

    1. Copy all the elements of the map to a std::vector and sort that:
    std::vector<std::pair<int,int> > v(hash.begin(), hash.end());
    std::sort(v.begin(), v.end(), [](const auto& a, const auto& b) { return a.second < b.second; });
    
    1. Copy all the elements of the map to another map with keys as values and values as keys. If values of your map are not unique, you can use a std::multimap instead.
    0 讨论(0)
  • 2021-01-29 08:35

    If you want to sort a std::map by its value, then you are using the wrong container. std::map is sorted by the keys by definition.

    You can wrap key and value:

    struct foo {
        int key;
        int value;
    };
    

    and then use a std::set<foo> that uses a comparator that only compares foo::value.

    0 讨论(0)
  • 2021-01-29 08:36

    This may be an X-Y issue.

    If you need to sort by both key and value, then a single std::map may not be the most efficient choice.

    In database theory, all the data would be placed into a single table. An index table would be created describing the access or sorting method. Data that needs to be sorted in more than one method would have multiple index tables.

    In C++, the core table would be a std::vector. The indices would be std::map<key1, vector_index>, std::map<key2, vector_index>, where vector_index is the index of the item in the core table.

    Example:

    struct Record
    {
      int age;
      std::string name;
    };
    
    // Core table
    std::vector<Record> database;
    
    // Index by age
    std::map<int, unsigned int> age_index_table;
    
    // Index by name
    std::map<std::string, unsigned int> name_index_table;
    
    // Fetching by age:
    unsigned int database_index = age_index_table[42];
    Record r = database[database_index];
    
    // Fetching by name:
    unsigned int database_index = name_index_table["Harry Potter"];
    Record r = database[database_index];
    

    You can learn more by searching the internet for "database index tables c++".

    If it looks like a database and smells like a database ...

    0 讨论(0)
  • 2021-01-29 08:41

    Simply put, you cannot. Not sure which compiler you're using, but clang and gcc both give useful messages. with context.

    clang: static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},

    gcc: if (__i == end() || key_comp()(__k, (*__i).first))

    You can see that clang and gcc are both calling the compare method with only they key, and not a value. This is simply how maps work.

    If you want to sort by value, you would have to create your own custom map, or, more realistically, use the value as the key instead. Creating your own map to achieve this would be more difficult than you'd think, since it would have to sort after any value is modified.

    0 讨论(0)
提交回复
热议问题