为什么我不能在 lambda 函数中使用 unordered_map?那里传递的参数的数据类型是什么?

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

这是我的代码,它根据字符的频率对字符串进行排序。

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 ;
    }

我收到这个错误:

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

lambda 的函数调用运算符 () 默认设置为 const,因此您必须通过引用(&umap&)传递映射,或使用 mutable 关键字使运算符 () 成为非常量并按值传递([umap]() mutable{}[=]() mutable{}):

通过引用传递地图:

#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;
}

按值:

#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;
}

您的 lambda 正在按值 捕获 unordered_map ,因此创建了一个副本。由于 lambda 未标记为 mutable,因此该副本将是 const。并且 operator[] 没有为 const unordered_map 实现,因为如果找不到请求的键,它需要能够修改 unordered_map 以插入新元素。因此错误:

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

您需要通过引用 来捕获 unordered_map

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

但是,您随后会运行陷入一个新的问题。 unordered_mapvalue_type 不是 char,而是 std::pair<const char, int>,因此这是您需要用于 lambda 参数的类型,在这种情况下会有根本不需要捕获 unordered_map:

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;
    }
);

但这也行不通。整个问题都没有实际意义,因为 you simply can't sort an unordered_map to begin with。它根据键哈希对其元素进行排序,您无法使用 std::sort().

更改该顺序

请参阅 sort an unordered_map using sort() and Sorting std::unordered_map by key 了解替代方案。