c++STL通过int和string的向量进行排序
c++ STL sort by a vector of int and string
今天我在解决一个关于面漆的问题,在这个问题中,我必须按照奥运会奖牌对国家进行排序。我有一个STL容器vector<pair<vector<int>, string> > v;
。vector<int>
不包含任何一个国家获得的金牌、银牌和铜牌。我必须按照金、银、青铜和国家(字母顺序)的特殊顺序对结构进行排序。
我使用了排序(v.begin(),v.end()),但这种排序只根据配对中的第一个值(即金牌、银牌和铜牌),当两个国家的g、s、b奖牌相同时,它不按字母顺序排列国家。
您必须提供比较函数对象。
typedef pair<vector<int>, string> Country;
struct CmpCountry {
bool operator()(const Country& lhs, const Country& rhs)
{
if(lhs.first[0] != rhs.first[0])
return lhs.first[0] > rhs.first[0];
if(lhs.first[1] != rhs.first[1])
return lhs.first[1] > rhs.first[1];
if(lhs.first[2] != rhs.first[2])
return lhs.first[2] > rhs.first[2];
return lhs.second < rhs.second;
}
};
// then, call sort as following
std::sort(v.begin(), v.end(), CmpCountry());
如果你真的写了你描述的代码,它会做你想要的事情:
compare.cpp:
#include <vector>
#include <utility>
#include <algorithm>
#include <iostream>
using namespace std;
typedef pair<vector<int>, string> Country;
int main(int, char*[]) {
vector<Country> v;
while (cin.good()) {
string name;
int g, s, b;
cin >> name >> g >> s >> b;
vector<int> c;
c.push_back(g);
c.push_back(s);
c.push_back(b);
v.push_back(make_pair(c, name));
}
sort(v.begin(), v.end());
for (vector<Country>::const_iterator it = v.begin(); it != v.end(); ++it) {
cout << it->second << " " << it->first[0]
<< " " << it->first[1] << " " << it->first[2] << "n";
}
return 0;
}
compare.in:
US 3 2 1
CA 4 1 3
DE 1 3 5
FR 1 3 5
BE 1 3 5
RU 3 1 2
现在这样做:
$ clang++ -o compare compare.cpp
$ ./compare < compare.in
BE 1 3 5
DE 1 3 5
FR 1 3 5
RU 3 1 2
US 3 2 1
CA 4 1 3
请注意,它是按金牌第一(先是BE/DE/FR,然后是RU/US,然后是CA)、银牌第二(RU,然后是US)、铜牌第二(尽管我没有输入),然后是名字(BE,然后是DE,然后是FR)排序的(升序)。正是你所要求的。
(实际上,你要求按字母顺序排列,这将对g、s和b进行数字顺序排列。这可能是你想要的(例如,2枚金牌大于11枚)。如果没有,则必须编写自己的比较函子,在比较int之前对其进行字符串化。)
那么,为什么这样做呢?如果你看一下std::pair
的定义,它按字典顺序进行比较——也就是说,它比较lhs.first
和rhs.first
,然后只有在first
相等的情况下,才转到lhs.second
和rhs.second
。如果你看一下std::vector
的定义,它也按照字典顺序进行比较——也就是说,它比较lhs[0]
和rhs[0]
,然后只有当[0]
相等时,才转到lhs[1]
和rhs[1]
,以此类推。这正是你在这里追求的比较顺序。
从你的评论中,听起来你想颠倒数值的正常排序顺序,但不想颠倒国家名称。要做到这一点,您必须定义自己的比较器。但请注意,问题不在于对和向量没有按照你想要的方式排序——它们确实如此——而是int没有按照你需要的方式排序。
如果你理解的话,这一切都是非常琐碎的,我会一步一步地解释,而不仅仅是给出答案。
首先,以下是默认排序(实际上,而不是字面上)要做的事情:
struct CountryComparator {
bool operator()(const Country& lhs, const Country& rhs) const {
if (!(lhs.first == rhs.first))
return (lhs.first < rhs.first);
return (lhs.second < rhs.second);
}
};
(请注意,我将尽量只使用==
和<
。这在您的情况下并不重要,因为您只是在比较int,但STL的设计理念是,即使在只支持这两个运算符的类上,每个算法也应该工作,这是一个好习惯。)
扩展向量比较会使事情变得非常冗长,所以我们不用麻烦了。如果你真的想反转向量中某些成员的排序顺序,而不是其他成员,你必须这样做,但你试图反转整个向量的排序顺序。这与反转向量本身的排序顺序相同。所以,只要定义一下:
struct CountryComparator {
bool operator()(const Country& lhs, const Country& rhs) const {
if (!(lhs.first == rhs.first))
return (rhs.first < lhs.first);
return (lhs.second < rhs.second);
}
};
现在,只需将排序行更改为:
sort(v.begin(), v.end(), CountryComparator());
现在让我们试试:
$ ./compare < compare.in
CA 4 1 3
US 3 2 1
RU 3 1 2
BE 1 3 5
DE 1 3 5
FR 1 3 5
CA获得4枚金牌,领先于其他所有人。然后,美国队和俄罗斯队各获得3枚金牌,按银牌排序;美国队获得两枚银牌,排名第一。然后,BE、DE和FR,每个都有1枚金牌,同样数量的银牌和同样数量的青铜器,按字母顺序排列。
您需要一个自定义比较器,以便STL排序可以比较您的向量。最简单的方法是将向量定义为struct,然后添加一个比较器。
struct country {
vector<int> medals;
string country_name;
}
struct compare {
bool operator()(country const &a, country const &b) {
for(int i = 0; i < 3; i++){ // 3 medals, right?
if(a.medals[i] != b.medals[i])
return a.medals[i] < b.medals[i];
//else both countries have same number of medals
return a.country_name < b.country_name;
}
};
- 将结构向量排序为子组
- C++数组与向量排序(在我的情况下,向量比数组慢~2.5倍(无优化))
- 如何在对向量排序后更改索引值?c++
- C++向量排序给出0作为输出
- 将许多向量排序在一起
- 根据一个向量对多个向量排序
- 编译错误向量排序和联合
- C++我自己的函数进行向量排序
- 将字符串的向量排序为日期"yyyymmdd"
- C++ 通过使用旧向量进行预排序来改进向量排序
- C 向量排序 .h .cpp中的单独文件
- 向量排序-c++
- 将向量排序到一个无序映射c++11中
- 向量的向量排序
- c++向量排序方法编译失败,返回预期表达式
- 如何对bitset向量排序
- 向量排序的基础上只有先
- 我如何以相同的方式对两个向量排序,而条件只使用其中一个向量
- 列表排序和结构体向量排序之间的性能差距.c++
- 如何基于第二个字符串对字符串向量的向量排序