【问题标题】:How can I sort the following map containing an integer and a pair?如何对包含整数和一对的以下地图进行排序?
【发布时间】:2015-07-01 21:12:40
【问题描述】:

所以,我有以下代码:

#include <iostream>
#include <unordered_map>
#include <utility>
#include <map>
using namespace std;

struct cmp 
{
    bool operator() (const pair<int,int>&a, const pair<int,int>&b)
    {
        if (a.first == b.first)
            return a.second<b.second;
        else
            return a.first > b.first;
    }
};
int main (void)
{
    int i=0,n,foo;
    cin>>n;
    map <int, pair<int,int>, cmp > mymap;
    while (i != n)
    {
        //auto it = mymap.begin();
        cin>>foo;
        if (mymap.find(foo) == mymap.end())
        {
            mymap[foo].make_pair(1,i);
        }
        else
        {
            mymap[foo].first++; 
        }
        i++;
    }
    auto it = mymap.begin();
    while (it != mymap.end())
    {
        cout<<it->first<<"\t"<<it->second.first<<"\t"<<it->second.second;
        cout<<"\n";
    }
    return 0;

}

这段代码所做的基本上是获取输入元素并按频率对它们进行排序(按降序排列)。如果两个元素的频率相同,则输出输入列表中最先出现的元素。

For ex: I/P: 2 5 2 8 5 6 8 8 
O/P: 8 8 8 2 2 5 5 6

我在两个地方有疑问。首先,在我编写的比较器函数中,它似乎是正确的,但它在编译时给出了一个错误,即,

no matching function for call to object of type 'const cmp'
        {return static_cast<const _Hash&>(*this)(__x);}

另外,我用于打印输出的循环是否正确,尤其是it-&gt;second.first

【问题讨论】:

  • unordered_maps 未排序,您想改用map
  • 即使有自定义比较器,也无法排序?
  • 另外,我将unordered_map 更改为map,但仍然显示相同的错误。
  • 看在上帝的份上,使用 typedefs,你不厌烦到处输入pair&lt;int,int&gt; 吗?

标签: c++


【解决方案1】:

cppreference.comstd::unordered_map被定义为

template<

    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;

由于这个容器是无序的,它不需要比较器来对元素进行排序。

因此,将您的(无序)地图定义为

    unordered_map <int, pair<int,int> > mymap;

即没有cmp

另外,不要忘记在最后一个 while 循环中增加迭代器,即添加 ++it,否则 ...

您的示例现在应该可以编译了:

$ ./mwe 
4
3
2
1
5
5   1   3
1   1   2
2   1   1
3   1   0

更新

参考您的评论,如果您将mymap 的类型从std::unordered_map 更改为 std::map,请记住元素将按其键排序。这不应该改变。 如果要按值对元素进行排序,请考虑以下替代方法:

使用std::vector,添加一个包含上述键和值的结构,并相应地更新您的cmp,例如

#include <algorithm>
#include <vector>
#include <tuple>

typedef std::tuple< int /* key */, int /* pair::first */, int /* pair::second */ > Element;
typedef std::vector< Element > ElementList;

template <int N>
bool cmp( const Element & a, const Element & b )
{
    return std::get< N >( a ) < std::get< N >( b );
}

int main()
{
    ElementList list;

    // Just dummy data, but you get the idea.
    list.push_back( std::make_tuple( 1, 2, 3 ) );
    list.push_back( std::make_tuple( 2, 3, 4 ) );
    list.push_back( std::make_tuple( 3, 4, 5 ) );

    // Sort by "pair::first", which is at element index 1 of 
    // the tuple, cf. cmp<1> below. Change this template parameter 
    // to the index value of the tuple element that should be used to 
    // sort your data.
    std::sort( list.begin(), list.end(), cmp<1> );

    return 0;
}

【讨论】:

  • 你真的需要创建一个自定义比较器来比较 2 个整数吗?
  • @Slava Thaha,非常渴望写一个我没有注意到明显的答案。感谢您的温柔提示。
  • 您能否详细说明您的比较器是如何工作的?我在这里有一个非常微不足道的疑问,有时我们将 bool 运算符包含在结构中(就像我在代码中所做的那样),有时,我们像您一样编写直接 bool 运算符,两者之间有什么区别以及何时使用?其次,为什么在cmp中传递1
  • 您使用了所谓的 Functor,我的示例使用了函数指针。有关详细信息,可以启动此SO question。 是模板参数;我在上面的示例中添加了注释。如果您喜欢答案,请随时将其标记为已接受。
【解决方案2】:

maps 按它们的键排序,而不是它们的值。考虑改用set

【讨论】:

  • 一个集合并不能真正解决我的问题,因此我可能不得不使用结构。
猜你喜欢
  • 2013-01-06
  • 2019-09-18
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 1970-01-01
  • 2010-09-15
  • 2014-06-21
  • 2017-09-22
相关资源
最近更新 更多