簡體   English   中英

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

[英]Iterating in a sorted manner over a std::vector<std::pair<T,U> > object

我正在從Foo類型的數據庫中讀取對象,如下所述。 該對象是Foo成員的向量,其中Foo成員由字符串id和容器對象組成。

typedef std::pair<std::string, Container> FooMember;
typedef std::vector<FooMember> Foo;

我希望以其排序形式迭代一個Foo對象,其中對id進行排序。 為此,我使用以下函數首先創建對象的排序版本。 如您所見,對象以不區分大小寫的方式排序。 與我目前的做法相比,我有更好的方法來迭代這個對象嗎?

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;
}

是:復制向量,然后將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);
  }
};

比填充地圖更有效,然后復制回矢量。

如果使用適當的Unicode排序規則算法,謂詞會更好,但標准庫或Boost中沒有。

最好的方法是使用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);
}

可以在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);
}

你可以使用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);
}

或者,您可以從一開始就將Foo對象保存在std::map<std::string, Foo> ,以便它們始終保持排序狀態。

您還可以將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; 
});

或者使用erelender提供的版本。 由你決定。

語義std::vector<std::pair<T,U> >std::map<T,U> (但實現通常是不同的)。 如果你可以重新設計Foo ,你可能會做得更好。 作為副作用,您將免費進行分類。

typedef std::map<std::string, Container> Foo;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM