0

以下に定義されているように、タイプ Foo のデータベースからオブジェクトを読み取っています。このオブジェクトは Foo メンバーのベクトルであり、Foo メンバーは文字列 ID とコンテナー オブジェクトで構成されます。

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

id に関して並べ替えが行われる、並べ替えられた形式で Foo オブジェクトを反復処理したいと考えています。これを行うには、次の関数を使用して、最初にオブジェクトの並べ替えられたバージョンを作成します。ご覧のとおり、オブジェクトは大文字と小文字を区別しない方法で並べ替えられます。現在行っている方法と比較して、このオブジェクトを反復処理するためのより良い方法はありますか?

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

5 に答える 5

4

はい: ベクトルをコピーしてから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 では利用できません。

于 2013-09-04T10:16:29.560 に答える
1

使用できます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>最初から に保持して、常にソートされたままにすることもできます。

于 2013-09-04T10:21:01.600 に答える
1

最善の方法は、次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);
}

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);
}
于 2013-09-04T10:16:30.910 に答える
-1

ラムダ式で std::sort を使用することもできます。

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 が提供するバージョンを使用します。それはあなた次第です。

于 2013-09-04T10:38:28.747 に答える
-3

意味的std::vector<std::pair<T,U> >にはstd::map<T,U>(ただし、実装は通常異なります)。を再設計できる場合はFoo、おそらくそれを行った方がよいでしょう。副作用として、無料で並べ替えを取得できます。

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

于 2013-09-04T10:29:45.010 に答える