简体   繁体   中英

Why am I not able to use the unordered_map in lamda function ? What is the data type of arguements being passed there?

Here is my code which sorts the string on the basis of frequency of chars.

string frequencySort(string s) {
        unordered_map<char,int> umap;
        
        for (int i=0 ; i<s.size() ; i++) 
            umap[s[i]]++ ;
        
        sort (s.begin() , s.end() , [umap] (char a , char b) {
            if (umap[a] == umap[b]) return a>b ;
            return umap[a]>umap[b] ;
        }) ;
        
        return s ;
    }

I'm getting this error:

Line 11: Char 21: error: no viable overloaded operator[] for type 'const unordered_map<char, int>'
            if (umap[c] == umap[d]) return a>b ;
                ~~~~^~
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/unordered_map.h:984:7: note: candidate function not viable: 'this' argument has type 'const unordered_map<char, int>', but method is not marked const
      operator[](const key_type& __k)
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/unordered_map.h:988:7: note: candidate function not viable: 'this' argument has type 'const unordered_map<char, int>', but method is not marked const
      operator[](key_type&& __k)
      ^

The lambda's function call operator () is by default set to const so you must either pass the map by reference ( &umap or & ), or use the mutable keyword to make the operator () non-const and pass by value ( [umap]() mutable{} or [=]() mutable{} ):

Passing the map by reference:

#include <iostream>
#include <algorithm>
#include <unordered_map>

std::string frequencySort(std::string s) {
    std::unordered_map<char,int> umap;

    for (int i=0 ; i<s.size() ; i++) 
        umap[s[i]]++ ;

    std::sort (s.begin() , s.end() , [&] (char a, char b) { // &umap
        if (umap[a] == umap[b]) return a>b ;
        return umap[a]>umap[b] ;
    }) ;

    return s;
}

int main()
{
    std::string s = "lollypop";
    std::cout << frequencySort(s);  // prints lllppooy
   return 0;
}

By value:

#include <iostream>
#include <algorithm>
#include <unordered_map>

std::string frequencySort(std::string s) {
    std::unordered_map<char,int> umap;

    for (int i=0 ; i<s.size() ; i++) 
        umap[s[i]]++ ;

    std::sort (s.begin() , s.end() , [=] (char a, char b) mutable {  // or [umap]
        if (umap[a] == umap[b]) return a>b ;
        return umap[a]>umap[b] ;
    }) ;

    return s;
}

int main()
{
    std::string s = "lollypop";
    std::cout << frequencySort(s);  // prints lllppooy
   return 0;
}

Your lambda is capturing the unordered_map by value , so a copy is made. Since the lambda is not marked as mutable , that copy will be const . And operator[] is not implemented for const unordered_map , since it needs to be able to modify the unordered_map to insert a new element if the requested key is not found. Hence the error:

no viable overloaded operator[] for type 'const unordered_map<char, int>'

You would need to capture the unordered_map by reference instead:

sort (s.begin(), s.end(),
    [&umap] (char a, char b) {
        if (umap[a] == umap[b]) return a > b;
        return umap[a] > umap[b];
    }
);

However, you will then run into a new problem. The value_type of your unordered_map is not char , it is std::pair<const char, int> , so that is the type you would need to use for your lambda parameters, in which case there would be no need to capture the unordered_map at all:

sort (s.begin(), s.end(),
    [] (const std::pair<const char, int> &a, const std::pair<const char, int> &b) {
        if (a.second == b.second) return a.first > b.first;
        return a.second > b.second;
    }
);

But that will not work either. This whole issue is moot, because you simply can't sort an unordered_map to begin with . It orders its elements based on key hashes, and you can't change that order using std::sort() .

See sort an unordered_map using sort() and Sorting std::unordered_map by key for alternatives.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM