2012-02-09 3 views
1

私は関数に渡される要素のベクトルをいくつか持っていますが、元のベクトルですが要素が1つもないすべてのベクトルを作成したいとします。サンプルベクトルに1つの要素がないベクトルをすべて作成するにはどうすればよいですか?

C++でこれを行う最も簡単な方法は何ですか?

私の現在のアプローチは次のようなものですが、まだまだ進んでいません。

std::vector<decltype(vec)> result; 
for (auto it(vec.begin()), end(vec.end()); it != end;) { 
    result.push_back(decltype(vec)(vec.begin(), it)); 
    result.back().insert(result.back().end(), ++it, vec.end()); 
} 
+0

あまりにも漠然とした、閉鎖されます。 – Nim

+0

あなたは私たちにいくつかのコードを表示すると、答えはかなりシンプルです! – guitarflow

+1

*最も簡単なのは、ベクトルの長さにわたって反復することです:コピーを作成し、そこからk番目の要素を削除します。それで十分ですか? – Beta

答えて

4

まあは、ちょうど現在、削除位置を特定し、この反復子の後に、このイテレータのすべてをバックアップし、すべてのベクトルを作成するためにイテレータを使用します。

#include <algorithm> 
#include <vector> 

// personally, I would pass "in" as a couple of iterators 
template<typename T> 
std::vector<std::vector<T>> list_one_removed(const std::vector<T>& in) 

{ 
    std::vector<std::vector<T>> result; 
    for (auto itor = in.begin(); itor != in.end(); ++itor) { 
     std::vector<T> buffer; 
     std::copy_if(in.begin(), 
        in.end(), 
        std::back_inserter(buffer), 
        [&itor](const T& t){ return &t != &(*itor); }); 
     result.emplace_back(std::move(buffer)); 
    } 
    return result; 
} 

あなたがループ "ごとに、" 新しいを持っている場合は、あなたが行うことができます:

#include <algorithm> 
#include <vector> 

template<typename T> 
std::vector<std::vector<T>> list_one_removed(const std::vector<T>& in) 
{ 
    std::vector<std::vector<T>> result; 
    for (const auto& foo : in) { 
     std::vector<T> buffer; 
     std::copy_if(in.begin(), 
        in.end(), 
        std::back_inserter(buffer), 
        [&foo](const T& t){ return &t != &foo; }); 
     result.emplace_back(std::move(buffer)); 
    } 
    return result; 
} 

あなたがC++ 03を使用している場合:あなたは、より詳細(入力/出力と、おそらくあなたの現在のコード)を追加しない限り

#include <algorithm> 
#include <vector> 

template<typename T> struct identity { 
    const T& id_; 
    identity(const T& id) : id_(id) { } 

    bool operator()(const T& other) const 
    { 
     return &id_ == &other; 
    } 
}; 

template<typename T> 
std::vector<std::vector<T> > list_one_removed(const std::vector<T>& in) 
{ 
    std::vector<std::vector<T> > result; 
    for (typename std::vector<T>::const_iterator itor = in.begin(); 
     itor != in.end(); 
     ++itor) { 
     std::vector<T> buffer; 
     std::remove_copy_if(in.begin(), 
          in.end(), 
          std::back_inserter(buffer), 
          identity<T>(*itor)); 
     result.push_back(buffer); 
    } 
    return result; 
} 
+0

答えをありがとう。私は少しの構文を理解するのに困っています。これでイテレータの現在の位置をスキップしますか?そして、 '結果'は果物オブジェクトのベクトルのベクトルですか?宣言型の表記法は私にとって初めてのものです。ありがとう:) – Jim

+1

最初に 'decltype(expr)'は式 'expr'の型を決定するだけです。 C++ 2011の新機能です。だから、結果はベクトルのベクトルです。これ以外にも、 'result 'の最後にイテレータを生成するイテレータのシーケンスの中にマジックがあります。イテレータは' [begin、it]というシーケンスから作成され、 '[++ it、end] '。 「現在の」要素をスキップする魔法は、それをスキップする '++ it'の中にあります。 –

0

<algorithm>およびC++ 11を使用した:

void list_one_removed(std::vector<Fruit> fruit) 
{ 
    for (unsigned i = fruit.size(); i > 0; i--) 
    { 
     // copy 'fruit' 
     // remove index i 
     // add this vector to some vector of vectors. 
    } 
} 
+0

Dietmarの答えはより効率的で、はるかに多くのあなたのC + + 03のバリアントは、最後に不必要なベクトルコピーを持つ必要があります。しかし、多くの比較とpush_backに起因する再割り当てを伴うC++ 11の亜種も最適ではありません。 –

+0

@Christian:私はもともと不必要な再割り当てを避けるために 'std :: vector :: reserve'を呼び出しました。しかし、私はそれらを削除しました。なぜなら、(1)サンプルコードが乱雑になりました。(2)10要素未満のベクトルについて話しています。 C++ 03のバージョンについては、リターン値の最適化と戻り値の最適化とコピー・エリジョンという名前について聞いたことがありますか? –

+0

さて、私は持っています。しかし、コンパイラを信じるだけで、このような単純な最適化(プッシュと一時的ではなく、プッシュの代わりに使用)を除外することはあまりありません。私は 'push_back'が' buffer'の内部コピーを実際に消去することは考えていません。const参照として受け取り、呼び出しの直後に 'buffer'が破棄されたことを知りません。新しい移動セマンティクスはために。 –

関連する問題