[英]Iterating in a sorted manner over a std::vector<std::pair<T,U> > object
I am reading a object from a database of type Foo, as defined below. 我正在从Foo类型的数据库中读取对象,如下所述。 This object is a vector of Foo Members, where a Foo Members consists of a string id and a container object.
该对象是Foo成员的向量,其中Foo成员由字符串id和容器对象组成。
typedef std::pair<std::string, Container> FooMember;
typedef std::vector<FooMember> Foo;
I wish to iterate over a Foo object in its sorted form, where sorting is done with respect to the id. 我希望以其排序形式迭代一个Foo对象,其中对id进行排序。 To do this I am using the following function to create first a sorted version of the object.
为此,我使用以下函数首先创建对象的排序版本。 As you can see, the object is sorted in a case insensitive manner.
如您所见,对象以不区分大小写的方式排序。 Is there a better way for me to iterate over this object compared to how I am currently doing it?
与我目前的做法相比,我有更好的方法来迭代这个对象吗?
Foo sortedFoo(Foo& value) const {
Foo returnValue;
returnValue.reserve(value.size());
// use a map to sort the items
std::map<std::string, FooMember> sortedMembers;
{
Foo::iterator i = value.begin();
Foo::iterator end = value.end();
for(; i!=end; ++i) {
std::string name = i->first;
boost::algorithm::to_lower(name);
sortedMembers[name] = *i;
}
}
// convert the map to a vector of its values in sorted order
std::map<std::string, FooMember >::iterator i = sortedMembers.begin();
std::map<std::string, FooMember >::iterator end = sortedMembers.end();
for(; i!=end; ++i) {
returnValue.push_back(i->second);
}
return returnValue;
}
Yes: Copy the vector, then use std::sort
with a custom comparison predicate: 是:复制向量,然后将
std::sort
与自定义比较谓词一起使用:
struct ByIdCaseInsensitive {
bool operator ()(const FooMember& lhs, const FooMember& rhs) const {
return boost::algorithm::to_lower_copy(lhs.first) <
boost::algorithm::to_lower_copy(rhs.first);
}
};
Way more efficient than filling a map, and then copying back to a vector. 比填充地图更有效,然后复制回矢量。
The predicate would be even better if it used a proper Unicode collation algorithm, but that isn't available in the standard library or Boost. 如果使用适当的Unicode排序规则算法,谓词会更好,但标准库或Boost中没有。
The best way would be to use std::sort
with a custom comparator for FooMembers
: 最好的方法是使用
std::sort
和FooMembers
的自定义比较器:
bool cmp(const FooMember& lhs, const FooMember& rhs);
Foo sortedFoo(const Foo& value) const
{
Foo tmp = value;
return std::sort(tmp.begin(), tmp.end(), cmp);
}
where the comparison can be implemented with the help of std::lexicographical_compare
and tolower
: 可以在
std::lexicographical_compare
和tolower
的帮助下实现比较:
#include <cctype> // for std::tolower
bool ci_cmp(char a, char b)
{
return std::tolower(a) < std::tolower(b);
}
#include <algorithm> // for std::sort, std::lexicographical_compare
bool cmp(const FooMember& lhs, const FooMember& rhs)
{
return std::lexicographical_compare(lhs.first.begin(),
lhs.first.end(),
rhs.first.begin(),
rhs.first.end(),
ci_cmp);
}
You can use std::sort
你可以使用
std::sort
#include <algorithm>
bool comparator(const FooMember& i, const FooMember& j)
{
std::string str1 = i.first;
boost::algorithm::to_lower(str1);
std::string str2 = j.first;
boost::algorithm::to_lower(str2);
return (str1 < str2);
}
void sortFoo(Foo& value) {
std::sort (value.begin(), value.end(), comparator);
}
Or, you can keep Foo
objects in a std::map<std::string, Foo>
from the beginning so they remain always sorted. 或者,您可以从一开始就将
Foo
对象保存在std::map<std::string, Foo>
,以便它们始终保持排序状态。
You can also use std::sort with a lambda expression: 您还可以将std :: sort与lambda表达式一起使用:
std::sort(value.begin(), value.end(), [](const FooMember &lhs, const FooMember &rhs)
{
std::string str1 = i.first, str2 = j.first;
boost::algorithm::to_lower(str1);
boost::algorithm::to_lower(str2);
return str1 < str2;
});
Or use the version provided by erelender. 或者使用erelender提供的版本。 It's up to you.
由你决定。
Semantically std::vector<std::pair<T,U> >
is a std::map<T,U>
(but implementations are usually different). 语义
std::vector<std::pair<T,U> >
是std::map<T,U>
(但实现通常是不同的)。 If you can re-design Foo
, you probably better do it. 如果你可以重新设计
Foo
,你可能会做得更好。 As side effect, you will get sorting for free. 作为副作用,您将免费进行分类。
typedef std::map<std::string, Container> Foo;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.