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.