- ベストアンサー
STLのlistで重複するものだけを取り出す方法
C++でVC++7.0を使用してプログラミングを学んでます。 ひとつハマっているのですが…、 STLのlistを利用して、重複するデータのみを一つにしたlistにしたいです。 例えば std::list<std::string> [1] bbb [2] aaa [3] bbb [4] ccc [5] eee [6] ddd [7] bbb [8] ccc と格納されたlistがあった場合に、 [1] bbb [2] ccc と2つ以上あるデータを1つのみ格納するようにしたいです。 重複するデータを省く処理なら思いつくのですが… (.sort()で重複するデータを並べ、.unique()で重複するデータを削除する) 上記のようなことは可能でしょうか? 何か有効な案がありましたら是非ご教授下さい!
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
1. まず,sort() して 2. adjacent_find() の結果をすべて新しいリストにpush_back()して 3. 最後にunique()をする というのが一番自然か. あるいは 1. まず,sort)したあと 2. binary_predをnot_equal_to<T>にしてunique()して 3. pop_front() して, 4. 最後に,普通のunique() でもいいような気もする.
その他の回答 (3)
- keibou21
- ベストアンサー率31% (18/58)
#3の訂正をします。 #include <map> std::map<std::string, int> list; list["bbb"]++; list["aaa"]++; list["ccc"]++; list["aaa"]++; などとして、 map<std::string, int>::iterator p; を経由して、 for(p = list.begin(); p != list.end(); p++) { p->first; // これで、index になっている方の、"aaa", "bbb", がソート済みで、しかも、重複なく、順次アクセスできます しかも、たとえば、list["aaa"] とすれば、"aaa" の数が参照できます。 の間違いだと思います。 あと、日本語等のマルチバイト文字列が入っている場合には意図した順番にソートされていない可能性があります。
お礼
回答・補足ありがとうございます。 非常にわかりやすくなりました。
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
正しい使い方ではないと思いますが…… vector ではなくて、map を使うというのは? #include <map> std::map<int, std::string> list; list["bbb"]++; list["aaa"]++; list["ccc"]++; list["aaa"]++; などとして、 map<std::string, std::string>::iterator *p; を経由して、 for(p = list.begin(); p != list.end(); p++) { p->second; // これで、index になっている方の、"aaa", "bbb", がソート済みで、しかも、重複なく、順次アクセスできます しかも、たとえば、list["aaa"] とすれば、"aaa" の数が参照できます。
お礼
回答ありがとうございます。 mapの特性を使うのも考えました。 しかし、listからmapに格納して またlistに戻すのは冗長なのかな?と思って考えてました。
- redfox63
- ベストアンサー率71% (1325/1856)
list<string>List1, List2; list<string>::iterator Iter1; // // 要素を格納の省略 // for( Iter1 = List1.begin(); Iter1 != List1.end(); ++Iter1 ) { // カウントで要素数を調べる if ( count(List1.begin(), List1.end(), *Iter1 ) > 1 ) { if (List2.empty() ) { List2.push_back( *Iter1 ); } else { // 抽出先のリストに 検査項目があるかを調べ // 無かった場合登録 if ( count(List2.begin(), List2.end(), *Iter1 ) == 0 ) { List2.push_back( *Iter1 ); } } } } for( Iter1 = List2.begin(); Iter1 != List2.end(); ++Iter1 ) { cout << *Iter1 << " "; } cout << endl;
お礼
回答ありがとうございます。 地道に比較して格納することも考えましたが、 何か方法があればと思いました。
お礼
回答ありがとうございます。 結局この手法を使わせていただきました。