2011-08-18 9 views
6

私はクラス "情報"を持っており、人の名前と年齢をベクトルに格納していると言います。C++でオブジェクトのベクトルをソート

そう...

class Information { 

private: 
int age; 
string name; 

//etc, etc... 
}; 

は、どのように私は、年齢に関して昇順/降順のいずれかでベクトルを並べ替えるでしょうか?

私はこのようなものを使用すると信じています。

sort(listOfPeople.begin(), listOfPeople.end(), greater<Information>()); 

listOfPeopleがベクターになります。

ご協力いただければ幸いです。その後、

class CompareInformations { 
    public: 
    // after making CompareInformations a friend class to Information... 
    operator(const Information& rhs, const Information& lhs) { 
     return rhs.age < lhs.age; 
    } 
}; 

そして、あなたの並べ替えを行います:

答えて

6

あなたは年齢によって非降順でそれらをソートしたい場合は、それを行うための一つの方法は、比較のためにファンクタを定義することです

sort(listOfPeople.begin(), listOfPeople.end(), CompareInformations()); 
また、あなたのクラスの operator<をオーバーロードし、比較対象なしで行うことができ

// inside your class 
bool operator <(const Information& rhs) { 
    return age < rhs.age; 
} 

そして、それを並べ替える:

sort(listOfPeople.begin(), listOfPeople.end()); 

上記の例は、あなたが非降順(ほとんど昇順ではなく、かなり)の順序でソートしたいと仮定します。 昇順ではないの注文を行うには、<のすべての出現を>に変更してください。

+0

CompareInformationsを情報に友だちクラスにすることは、どういう意味ですか? – user432584920684

+0

@Vincentのように、 'age'はプライベート変数で、' CompareInformations'クラスはその変数にアクセスします。それは許可されていないので、あなたにエラーを与えるでしょう。しかし、 'friend class CompareInformations;'を 'Information'の定義のどこかに置くと、' CompareInformations'がそのクラスのプライベートメンバーにアクセスできるようになります。あるいは、単に 'rhs.age'へのアクセスを' rhs.getAge() 'やあなたが定義したアクセサに置き換えることもできます。 –

+0

うん、私はrhs.getAge()を使用しました。コンパイルしようとすると次のエラーメッセージが表示されます。 エラー: 'int情報:: getAge()'の 'this'引数として 'const情報'を渡すと修飾子が破棄されるtestone.cpp – user432584920684

3

2つのInformation参照を取り、最初のものが2番目のものの前に注文される場合はtrueを返すコンパレータ関数またはファンクタクラスを作成する必要があります。

以下は最年少の古いものからソートします:昇順または降順にソートするかどうかを選択するには

bool CompareAges(const Information & left, const Information & right) 
{ 
    return left.age > right.age; 
} 

std::sort(listOfPeople.begin(), listOfPeople.end(), CompareAges); 

、あなたは別の比較関数とsortには、2つの異なる呼び出しを持つことができる、またはあなたがその数子クラスを作成することができます項目のソート方法を決定するフラグがあります。

struct CompareAgesUpOrDown 
{ 
    CompareAgesUpOrDown(bool bDown) : m_bDown(bDown) {} 
    bool operator() (const Information & left, const Information & right) 
    { 
     if (m_bDown) 
      return left.age < right.age; 
     else 
      return left.age > right.age; 
    } 
    bool m_bDown; 
}; 

bool bDown = ...; 
std::sort(std::sort(listOfPeople.begin(), listOfPeople.end(), CompareAgesUpOrDown(bDown)); 
+0

私はそれを正しくやっているのかどうかはわかりませんが、最初のコードブロックを実装しようとすると、compile.testone.cppを実行しようとすると次のような結果が出ます:27:error: 'const' 'int Information :: getAge()'は修飾子を破棄します testone.cpp:27:エラー: 'const'を 'int'の情報:: getAge()で渡すと 'const情報'が修飾子を破棄します – user432584920684

+0

@Vincent mark 'getAge' 'const'として –

+0

申し訳ありませんが、私はこれでかなり新しいです。どのくらい正確にgetAgeをconstとしてマークしますか? – user432584920684

0

私はoperator <をオーバーロードし、より大きい値を使用して並べ替えます。 Greaterは本質的にrhs < lhsを意味する。あなたはstd::setと、ソートを可能にすることに加えてstd::mapでキーとしてうまく再生されましたoperator<あなたのクラスを追加することを決定した場合、あなたはその後、ソート

sort(listOfPeople.begin(), listOfPeople.end(), greater<Information>());を使用します。

class Information { 

private: 
int age; 
string name; 

friend bool operator< (Information const& lhs, Information const& rhs){ 
    return lhs.age < rhs.age; 
} 

//etc, etc... 
}; 
+0

これはメンバー関数ではなく、友人関数である理由は何ですか? –

+0

習慣の力。私は通常、算術型を扱い、フリー関数が変換の恩恵を受けるようにしたい。 – Flame

1

このような並べ替えを使用するには、比較関数またはオブジェクトが必要です。例と情報については、sort page at cplusplus.comをご覧ください。

はここで比較関数を使用した完全な例です:

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 

class Information { 
public: 
    Information(int age, std::string name) : m_age(age), m_name(name) {} 
    int age() const { return m_age; } 
    std::string name() const { return m_name; } 
private: 
    int m_age; 
    std::string m_name; 

    friend bool sortInformationByAgeAscending(const Information& lhs, 
              const Information& rhs);  
    friend bool sortInformationByAgeDescending(const Information& lhs, 
              const Information& rhs); 
}; 

bool sortInformationByAgeAscending(const Information& lhs, 
            const Information& rhs) { 
    return lhs.m_age < rhs.m_age; 
} 

bool sortInformationByAgeDescending(const Information& lhs, 
            const Information& rhs) { 
    return lhs.m_age > rhs.m_age; 
} 
int main (int argc, const char * argv[]) 
{ 
    std::vector<Information> info; 
    info.push_back(Information(1, "Bill")); 
    info.push_back(Information(5, "Ann")); 
    info.push_back(Information(2, "Sue")); 

    std::sort(info.begin(), info.end(), sortInformationByAgeAscending); 

    std::cout << info.at(0).age() << ": " << info.at(0).name() << std::endl; 
    std::cout << info.at(1).age() << ": " << info.at(1).name() << std::endl; 
    std::cout << info.at(2).age() << ": " << info.at(2).name() << std::endl; 

    return 0; 
} 
+0

+1努力(長さ) –

2

その他は、すでにC++ 98/03解決策を示しています。発生すると、それを実現すべき場合には、

// ascending age: 
std::sort(people.begin(), people.end(), 
      [](person const &a, person const &b) { return a.age < b.age; }); 

// descending age: 
std::sort(people.begin(), people.end(), 
      [](person const &a, person const &b) { return b.age < a.age; }); 

そして:C++ 11では、あなたの代わりにあなたの比較のために、ラムダを使用する場合があります

// ascending name: 
std::sort(people.begin(), people.end(), 
      [](person const &a, person const &b) { return a.name < b.name; }); 

// descending name: 
std::sort(people.begin(), people.end(), 
      [](person const &a, person const &b) { return b.name < a.name; }); 

IMO、Informationは名前が一般的すぎます、私はそれをpersonに変更しました。 ContrariwiseのlistOfPeopleは、コンテンツではなくフォームに重点を置いています(さらに悪いことに、実際にはリストを持たず、人々のベクトルを持っているので間違っています)。 IMOでは、プログラミングでは一般的にリニアデータ構造ではなく、リンクリストを参照するためにlistを使用する方が一般的に優れています。

+0

ありがとう、私はあなたのヒントを念頭に置いておきます。 ちょうど質問、私はあなたがこのように実装する場合、bool比較関数を必要としないと思いますか?私は帰宅するときにこのコードを試してみます。 – user432584920684

+0

@Vincent:はい。ラムダを使用すると、別々の代わりに比較コードをインラインで指定できます。 FWIW、通常は1つの注文を使用している場合は、それをクラスの 'operator <'に入れて、他の場合の順序を明示的に指定するだけです。 –

関連する問題