ページ 11

vector<string>の重複要素を削除する

Posted: 2010年7月18日(日) 13:52
by dic
3連休ですね
人によっては4連休かもですね

質問ですが vector<string> 変数の内容で重複している内容を削除したいのです
ソースコードは下のような感じです
//=========================================
void a()
{
    vector<string>    v;
    char    buf[1024];
    int    i;
    for( i=0; i<100; i++ )
    {
        sprintf( buf, "%d", i/10 );
        v.push_back( buf );
    }
    //    ここで重複要素を削除したい
}
前にも質問し unique を使うような記憶があったんですが、
発言内容を覚えてなくて検索ができないので
もう一度質問させてください
vector<string>::iterator を使ったのは覚えています

Re:vector<string>の重複要素を削除する

Posted: 2010年7月18日(日) 15:41
by めるぽん
ソートされちゃってもいいのであれば、
std::vector<string> v;
// v に値を設定する
std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());
とすればいけます。

ソートされちゃうのが嫌な場合はちょっと面倒ですね。
その場合は少しやり方を考える必要があります。 画像

Re:vector<string>の重複要素を削除する

Posted: 2010年7月18日(日) 15:58
by たいちう
// 例えばこう
void func() {
    vector<string> v;
    for (int i = 0; i < 100; i++ ) {
        stringstream ss;
        ss << (i / 10);
        v.push_back(ss.str());
    }

    set<string> s(v.begin(), v.end());
    v = vector<string>(s.begin(), s.end());

    for (vector<string>::iterator it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
}

// このような場合なら最初からsetを使っても良いかも
void func2() {
    set<string> s;
    for (int i = 0; i < 100; i++ ) {
        stringstream ss;
        ss << (i / 10);
        s.insert(ss.str());
    }

    for (set<string>::iterator it = s.begin(); it != s.end(); it++)
        cout << *it << endl;
}

Re:vector<string>の重複要素を削除する

Posted: 2010年7月18日(日) 17:22
by めるぽん
たいちうさんみたいに set を使えば、結構簡単にソートせずに重複を確認していくというのができそうですね。
std::vector<std::string> v;
// v に値を設定する

std::set<std::string> set;
std::vector<std::string> result;
for (std::vector<std::string>::iterator it = v.begin(); it != v.end(); ++it)
{
    if (set.insert(*it).second)
        result.push_back(*it);
}
// result にソートされていない unique な値が入っている
で、あとはこの処理を汎用的に使えるようにしておくといいかもしれませんね。
// *a < *b で比較するための predicate
struct direct_less
{
    template<class Iterator>
    bool operator()(const Iterator& a, const Iterator& b) const
    {
        return *a < *b;
    }
};

template<class Iterator, class OutputIterator>
void unique_no_sort(Iterator first, Iterator last, OutputIterator out)
{
    // 要素をコピーするのはコストがでかいので Iterator を格納するようにする
    std::set<Iterator, direct_less> set;
    for (; first != last; ++first)
    {
        if (set.insert(first).second)
            *out++ = *first;
    }
}
こんなのを作っておけば、
std::vector<std::string> v;
// v に値を設定する
std::vector<std::string> result;
unique_no_sort(v.begin(), v.end(), std::back_inserter(result));
// result に unique な値が入っている
とかできるようになります。

Re:vector<string>の重複要素を削除する

Posted: 2010年7月18日(日) 17:55
by dic
めるぽんさん たいちうさん
回答ありがとうございます

条件書いてなかったですね すいません
ソートしても大丈夫な環境です

参考にさせてもらい、解決しました


>stringstream
初めてみました・・・
私の持っている本には載ってないですね
世界(C/C++)は広い・・・