web-dev-qa-db-ja.com

要素がstd :: vectorの最初または最後の要素であるかどうかを確認します

次の_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::_方法はありますか?

21
Mendes

この場合、このような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の回答も参照してください。

20
vsoftco

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>特殊化では機能しません。ビットを使用してブール値を効率的に格納するためにベクトルを最適化し、ビットへの参照を取得できないため、このデータ構造から取り出されるすべての参照は厳密に結び付けられていないプロキシオブジェクトです内部データのアドレスへ。

20
Denilson Amorim

最初の要素には 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
5
R Sahu

値ベースの比較では、myVector.front()/_myVector[0]_を最初の要素として使用し、myVector.back()/myVector[myVector.size()-1]を最後の要素として使用できます。

提案
不要なコピーを避けるために、デフォルトで参照をキャプチャします。例えば.

for(const auto& I : myVector)

3
iammilind

もう一度検索することもできますが、それはかなり非効率的です。現在のアイテムの位置に関する情報が必要な場合は、おそらくイテレータまたはインデックスを使用する必要があります。

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;
}
2
isanae

境界に特殊なケースがある場合は、ol 'イテレータバージョンを使用する必要がありますが、最初のケースと最後のケースをループから切り離してください。

ケースがその後コードを共有する場合、関数にカプセル化する必要がある場合。

電話からコードを書くことができません:c

2
Dietr1ch

これは私のために働く

vector<int> vi {1,2,3,4};

cout << "vi = {";
for (const auto &e : vi) {
  cout << e;

  if (&e != &vi.back())
    cout << ',';
}
cout << '}' << endl;
0
jafox
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番目の文字が最後の文字と同じ場合、これは機能しません。

0
Hua Fan