次の_for each
_ C++コードがあります。
_for (auto item : myVector)
{
std::cout << item;
if (item == orderBy.IsLast()) // <--- Check if this is the last element
std::cout << "(Is last element) " << std::endl;
else if (item == orderBy.IsFirst()) // <-- Check if this is the first element
std::cout << "(Is first element)" << std::endl;
}
_
もちろんIfLast()
とIfFirst()
は_std::vector
_に存在しません。最初と最後の要素をチェックするネイティブの_std::
_方法はありますか?
この場合、このようなfor
はイテレータを「隠す」ため、範囲ベースのfor
を使用しないでください。また、位置を追跡するために追加のカウンターが必要です。ベクター。簡単にできます
_for(auto it = myVector.begin(); it != myVector.end(); ++it)
{
if(it == myVector.begin()) // first element
{
// do something
}
else if(std::next(it) == myVector.end()) // last element
{
// do something else
}
}
_
my.Vector.back()
を範囲ベースのforの要素と単純に比較することは、ベクトルに重複がないことが確実な場合にのみ問題ないことに注意してください。しかし、例えば最後の要素の値がベクトル内に複数回出現する場合、最初の位置のみを見つけます。そのため、範囲ベースのfor
を使用する良い方法は、ベクターの正確な位置を追跡する追加のインデックスなしでは本当にありません。
[〜#〜] edit [〜#〜]範囲ベースのfor
を「トリック」する方法については、暗黙的に要素の位置を取得できる@ thelink2012の回答も参照してください。
std::vector::front
および std::vector::back
を使用して、referenceを取得します最初と最後の位置のデータ。
参照は、繰り返しのitem
のアドレスと、それぞれのフロント/バックリファレンスのアドレスを効率的に確認できるため、ここでキーワードになります。この例では、item
を参照ではなく値で取得するため、これはおそらく機能しないでしょう。このメソッドで機能するこの例を考慮してください。
for(auto& item : myVector) // take item by reference
{
std::cout << item;
if (&item == &myVector.back())
std::cout << "(last element) " << std::endl;
else if (&item == &myVector.front())
std::cout << "(first element)" << std::endl;
}
オブジェクトが演算子&
のアドレスをオーバーロードする場合(悪い習慣と見なされますが)使用したい場合があります std::addressof
代わりに。
ただし、このメソッドはstd::vector<bool>
特殊化では機能しません。ビットを使用してブール値を効率的に格納するためにベクトルを最適化し、ビットへの参照を取得できないため、このデータ構造から取り出されるすべての参照は厳密に結び付けられていないプロキシオブジェクトです内部データのアドレスへ。
最初の要素には std::vector::front()
を使用します。
最後の要素には std::vector::back()
を使用します。
これらの関数を呼び出す前に、vector
が空でないことを確認してください。
if (!orderBy.empty() && item == orderBy.back()) <--- Check if this is the last element
else if (!orderBy.empty() && item == orderBy.front()) <-- Check if this is the first element
値ベースの比較では、myVector.front()
/_myVector[0]
_を最初の要素として使用し、myVector.back()
/myVector[myVector.size()-1]
を最後の要素として使用できます。
提案
不要なコピーを避けるために、デフォルトで参照をキャプチャします。例えば.
for(const auto& I : myVector)
もう一度検索することもできますが、それはかなり非効率的です。現在のアイテムの位置に関する情報が必要な場合は、おそらくイテレータまたはインデックスを使用する必要があります。
for (std::size_t i=0; i<myVector.size(); ++i)
{
auto& item = myVector[i];
std::cout << item;
if (i == (myVector.size() - 1))
std::cout << "(Is last element) " << std::endl;
else if (i == 0)
std::cout << "(Is first element)" << std::endl;
}
境界に特殊なケースがある場合は、ol 'イテレータバージョンを使用する必要がありますが、最初のケースと最後のケースをループから切り離してください。
ケースがその後コードを共有する場合、関数にカプセル化する必要がある場合。
電話からコードを書くことができません:c
これは私のために働く
vector<int> vi {1,2,3,4};
cout << "vi = {";
for (const auto &e : vi) {
cout << e;
if (&e != &vi.back())
cout << ',';
}
cout << '}' << endl;
vector<int> vi {1,2,6,4,5,6};
cout << "vi = {";
for (const auto &e : vi)
{
cout << e;
if (&e != &vi.back())
cout << ',';
}
cout << '}' << endl;
3番目の文字が最後の文字と同じ場合、これは機能しません。