使用键和值

时间:2015-09-26 09:18:29

标签: c++ algorithm sorting dictionary multimap

我试着通过为它编写一个比较函数来使用标准排序函数对其中包含一组对的多图进行排序,但我收到了一些错误。我正在尝试使用值对地图进行排序,然后再次使用键对其进行排序。比较功能导致一些错误。你能指出我错在哪里吗?

#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

bool cmp(const pair<int,int>& a, const pair<int,int>& b)
{
    return a.second < b.second;
}

int main() {
    // multimap of int ssId, int phone numbers
    multimap <int, int> m;
    m.insert(make_pair(1, 8));
    m.insert(make_pair(1, 5));
    m.insert(make_pair(2, 4));
    m.insert(make_pair(2, 3));
    m.insert(make_pair(3, 1));

    sort(m.begin(), m.end(), cmp);
    return 0;
}

输出应该如下:

1 5
1 8
2 3 
2 4
3 1

4 个答案:

答案 0 :(得分:2)

在 C++ 中没有直接的方法可以做到这一点,因为 multimap 是有序的,其顺序不能改变,但有一个使用额外的 multimap 的解决方法。它会输出你喜欢的东西。类似的方法适用于字符串到整数,反之亦然。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    multimap <int, int> m;
    m.insert(make_pair(1, 8));
    m.insert(make_pair(1, 5));
    m.insert(make_pair(2, 4));
    m.insert(make_pair(2, 3));
    m.insert(make_pair(3, 1));
    multimap<int, int> R;
    for (auto i=m.begin(); i!=m.end(); i++)
        R.insert({i->second,i->first});
    m.clear();
    for (auto i=R.begin(); i!=R.end(); i++)
        m.insert({i->second,i->first});
    R.clear();
    for (auto i=m.begin(); i!=m.end(); i++)
        cout<<i->first<<"\t"<<i->second<<endl;
    return 0;
}

答案 1 :(得分:1)

您正在尝试对严格排序的容器进行排序。这是不可能的,因为整个swap中两个元素的multimap将违反其一般的弱序。例如,您提供的cmp(只是想象)“已排序”m将是:

3 1
2 3
2 4
1 5
1 8

如您所见,违反了m的排序。

关联容器不关心值的排序。如果您需要订购,那么

  • 使用另一个有序容器作为值(例如std::map<int, std::set<int>>
  • 使用std::set<std::pair<int, int>, cmp>订阅自定义cmp。但请注意,它不是地图:

    1. 您将无法仅通过ssId访问元素,但您可以按lower_bound()upper_bound()
    2. 访问范围
    3. std::set的元素是不可变的。这意味着要更改std::set的元素,您必须从集合中删除它们,然后插入更新的值。

std::set< std::pair<int, int> > m;

m.insert(make_pair(1, 8));
m.insert(make_pair(1, 5));
m.insert(make_pair(2, 4));
m.insert(make_pair(2, 3));
m.insert(make_pair(2, 1));
m.insert(make_pair(2, 5));
m.insert(make_pair(2, 2));
m.insert(make_pair(2, 0));
m.insert(make_pair(3, 1));

for(auto&& x : m) {
    std::cout << x.first << ' ' << x.second << std::endl;
}

auto b = m.lower_bound(std::make_pair(2, 2));
auto e = m.lower_bound(std::make_pair(2, 4));

std::cout << std::endl;

for(auto i = b; i != e; ++i) {
    std::cout << i->first << ' ' << i->second << std::endl;
}

将产生

  

1 5
  1 8
  2 0
  2 1
  2 2
  2 3
  2 4
  2 5
  3 1

     

2 2
  2 3

注意,std::pair以及std::tuple已经有词典比较运算符。

答案 2 :(得分:0)

这是一个老问题,但如果他们正在寻找,可能对其他人有用。

对于这种我们希望为相同的键对值进行排序的场景, 而不是使用

multimap <int, int> m;

使用

map<int,vector<int>> and then sort the individual vector.
or even better, just:
vector<pair<int,int>> and then sort the vector

vector<pair<int, int>> vec{{1,8}, {1,5},{2,4} ,{2,3}, {3,1}};
sort(begin(vec), end(vec));

pair 的内部排序将按第一个元素进行排序,当第一个元素相同时,它按第二个元素对这些对进行排序。

答案 3 :(得分:-1)

你做不到。 C ++中的Multimap STL是有序的,订单不能/不能改变(我认为在底线它使用平衡二叉树来表示我认为的密钥,但不确定)。

你可以做的是实例化一个新的multimap对象,传递一个符合你需要的比较器(研究严格的弱秩序)。

默认情况下,使用less,与升序进行比较。在下面的示例中,您可以看到传递给比较器的模板参数的greater比较器对象,它与降序进行比较。 比较器仅比较键,而不是值。

如果需要,您可以传递自己的比较器,或者为要存储在地图中的类型(键)定义自己的<运算符。

请参阅下面的示例以了解用法。

// multimap
#include <map>
#include <iostream>
#include <functional>
#include <iomanip>

using namespace std;

template<class T> void print(T start, T end) {
    while (start != end) {
        std::cout << start->first << ":" << start->second << " ";
        start++;
    }
}

template<class T, class U> void fillMap(multimap<T, T> & m, U start, U end) {
    for (; start != end; ++start) {
        m.insert(pair<T, T>(*start, *start));
    }
}

int main() {
    int t[] = {2, 10, 8, 4, 5, 5, 3, 10, 7, 2};
    //1. standard initialization - default constructor
    multimap<int, int > m1;
    fillMap(m1, t, t + 10);
    //2. iterator constructor
    multimap<int, int> m2(m1.begin(), m1.end());
    //2b. iterator constructor - wrong
    //multimap<int, int> m2(t, t+10);
    print(m2.begin(), m2.end());
    cout << endl;
    //3. copy constructor
    multimap<int, int> m3(m2);
    print(m3.begin(), m3.end());
    cout << endl;

    //4. providing different comparator
    multimap<int, int, greater<int> > m4(m1.begin(), m1.end());
    print(m4.begin(), m4.end());
    cout << endl;
    //5. Not allowed - source and target object are not of the same type 
    //multimap<int, greater<int> > s5 (s3);

    //6. assignment
    multimap<int, int> m6;
    m6 = m3;
    print(m6.begin(), m6.end());
    cout << endl;
    //7. Not allowed - assignment of incompatible multimap objects
    //m6 = m4;
    return 0;
}