私はPythonの学習に取り組んでおり、どういうわけか次のコードを思いつきました:
for item in list:
while list.count(item)!=1:
list.remove(item)
この種のコーディングが c++ でできるかどうか疑問に思っていました。(サイズを小さくしながら for ループのリストの長さを使用する)そうでない場合は、誰か教えてもらえますか?
ありがとう!
私は大した Python プログラマーではありませんが、上記のコードはリストから重複を削除するようです。C++ に相当するものを次に示します。
list.sort();
list.unique();
それを繰り返しながらリストを変更することに関しては、それも行うことができます。次に例を示します。
for (auto it = list.begin(), eit = list.end(); it != eit; ) {
if (std::count(it, eit, *it) > 1)
it = list.erase(it);
else
++it;
}
それが役に立てば幸い。
私はPythonを知りませんが、誰かがコメントでリストはC ++ベクトルと同等であり、ソートされていないので、ここに行きます...と言いました。
std::vector<int> v{1, 2, 2, 2, 3, 3, 2, 2, 1};
v.erase(std::unique(v.begin(), v.end()), v.end());
v
{1, 2, 3, 2, 1}
このコードの後に含まれています。目標が(連続した重複だけでなく)すべての重複を削除することである場合は、最初にベクトルを並べ替える必要があります。std::sort(v.begin(), v.end());
C++ では、条件によっては、反復処理中にコンテナーから要素を削除できます。これは、コンテナーと実行する操作によって異なります。
現在、さまざまな回答でコード スニペットの解釈が異なります。私の解釈は、リストに複数存在するすべての要素を削除したいということです。
C++ での解決策は次のとおりです。最初に別のコンテナー (std::map) 内の要素をカウントし、その後リストから適切な要素を削除します。
#include <list>
#include <map>
#include <algorithm>
#include <iostream>
int main() {
std::list<int> li { 0, 1, 2, 3, 4, 5, 1, 2, 3, 2, 2 };
// Create count map: element -> count
std::map<int, int> cm;
std::for_each( li.begin(), li.end(), [&cm](int i) { ++cm[i]; } );
// Remove all elements from list with count > 1
std::for_each( cm.begin(), cm.end(),
[&li](std::pair<const int, int> const p) {
if( p.second > 1) {
li.remove( p.first );
}
} );
// Output all elements from remaining list
std::for_each( li.begin(), li.end(),
[](int i) { std::cout << i << std::endl; } );
return 0;
}
C++ では、標準ライブラリのさまざまなアルゴリズムからこのようなものを構成できます。remove()、find() を確認してください。ただし、アルゴリズムの記述方法は、O(n^2) の複雑さのように見えます。リストをソートし、それをスキャンして各値の 1 つを新しいリストに入れると、O(n log n) の複雑さがありますが、順序が崩れます。
一般に、Python と C++ の両方で、要素を一時コンテナーにコピーまたは移動してから、元のインプレースを変更するよりも元のコンテナーと交換する方がよい場合がよくあります。これは、自分の足で踏まないため (delnan のコメントを参照)、正しく行うのが簡単であり、オブジェクトの再割り当てとコピーの繰り返しが回避されるため、より高速です。
これが私がそれを行う方法です。
//If we will not delete an element of the list
for (std::list<MyType>::iterator it = MyList.begin(); it != MyList.end();++it)
{
//my operation here
}
//If we will delete an element of the list
for (std::list<MyType>::iterator it = MyList.begin(); it != MyList.end();)
{
std::list<MyType>::iterator itt = it;
++itt;
MyList.erase(it);
it = itt;
}
リストのサイズを使用できますが、[it] であるため、[it] とは比較になりません。
std:: データ クラスの特定の機能は、設計上の決定として有効または無効になっています。確かに、独自の関数 MyList[int i] を作成することはできますが、リストの性質上、大幅な速度低下につながります。
std::vector
は、Python の に最もよく似た C++ のコンテナーですlist
。ベクターを繰り返しながら変更する正しい方法は次のとおりです。
template <typename T>
void dedupe(std::vector<T> &vec) {
for (std::vector<T>::iterator it = vec.begin(); it != vec.end(); ) {
if (std::count(vev.begin(), vec.end(), *it) != 1) {
it = vec.erase(it);
} else {
++it;
}
}
}
これは必ずしも最も効率的な重複排除方法ではありませんが、機能します。
サイズを減らしながら for ループにリストの長さを使用する
ではなく長さを使用することを主張する場合end()
は、イテレータの代わりにインデックスを使用できます。
template <typename T>
void dedupe(std::vector<T> &vec) {
for (std::vector<T>::size_type pos = 0; pos != vec.size(); ) {
if (std::count(vec.begin(), vec.end(), vec[pos]) != 1) {
vec.erase(vec.begin() + pos);
} else {
++pos;
}
}
}
ちなみに、Python コードの意図はすべての重複を削除することであり、そうでないという事実はバグであると想定しています。たとえば、入力[2,2,1,3,3,1,2,3]
、出力[1,1,2,3]
。あなたが言ったことがあなたが意図したものである場合、コードを C++ に直接翻訳すると次のようになります。
template <typename T>
void dedupe(std::vector<T> &vec) {
for (std::vector<T>::size_type pos = 0; pos < vec.size(); ++pos) {
T item = vec[pos];
while (std::count(vec.begin(), vec.end(), item) != 1) {
vec.erase(std::find(vec.begin(), vec.end(), item));
}
}
}