简体   繁体   English

在std :: vector上以有序的方式迭代 <std::pair<T,U> &gt;对象

[英]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::sortFooMembers的自定义比较器:

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_comparetolower的帮助下实现比较:

#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.

相关问题 构造一个std :: map <T,U> 从std :: vector <std::pair<T,U> &gt; - Construct a std::map<T,U> from a std::vector<std::pair<T,U> > 在std :: vector上均匀地迭代 <T> 和std :: vector <unique_ptr<T> &gt; - Iterating uniformly over std::vector<T> and std::vector<unique_ptr<T>> 在std :: vector中遍历const T& <std::unique_ptr<T> &gt; - Iterating over const T& in a std::vector<std::unique_ptr<T> > std :: is_assignable和std :: pair <const T,U> - std::is_assignable and std::pair<const T, U> 迭代std :: map <X,std::vector<Y> &gt;并对矢量进行排序 - Iterating over std::map<X,std::vector<Y> > and sorting the vectors 绑定const std :: pair <T, U> &到std :: pair的值 <const T, U> - Bind const std::pair<T, U>& to value of std::pair<const T, U> 尝试投射std :: vector时遇到VS编译器警告C4239 <std::pair<T, U> &gt;至其左值参考 - Got VS compiler warning C4239 when trying to cast std::vector<std::pair<T, U>> to its lvalue ref 在std :: vector中找到<std::pair> - find in std::vector<std::pair> 我的哪种情况会std :: map <A,B> 比排序的std :: vector更快 <std::pair<A,B> &gt;? - I which situation will std::map<A,B> be faster than sorted std::vector<std::pair<A,B>>? 安全修改std :: pair <U, V> ::成对向量中的第一个? - Safe To Modify std::pair<U, V>::first in vector of pairs?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM