C++ 检查元素是 std::vector 中的第一个还是最后一个

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30205158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:43:27  来源:igfitidea点击:

Check if the element is the first or the last one in an std::vector

c++c++11for-loop

提问by Mendes

I have the following for eachC++ code:

我有以下for eachC++ 代码:

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

Of course IfLast()and IfFirst()do not exist on std::vector. Is there a native std::way to check for first and last element ?

当然IfLast()IfFirst()并不存在于std::vector。是否有一种本地std::方式来检查第一个和最后一个元素?

采纳答案by vsoftco

You shouldn't use the range-based forin this case, as this kind of for"hides" the iterator, and you'd need an additional counter to keep track of the position in vector. You can simply do

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
    }
}

Note that simply comparing my.Vector.back()with your element from a range-based for is OK only if you're sure that you don't have duplicates in the vector. But if e.g. the value of the last element appears multiple times in the vector, you're going to find only its first position. So that's why there's really no good way of using a range-based forwithout an additional index that keeps track of where exactly in the vector you are.

请注意,my.Vector.back()仅当您确定向量中没有重复项时,才可以简单地与基于范围的元素进行比较。但是如果例如最后一个元素的值在向量中出现多次,你将只找到它的第一个位置。所以这就是为什么在没有for额外索引的情况下使用基于范围的方法真的没有好方法来跟踪您在向量中的确切位置。

EDITSee also @thelink2012's answer for how to "trick" your range-based forso you can get the position of the element implicitly.

编辑另请参阅@thelink2012 的答案,了解如何“欺骗”基于范围的内容,for以便您可以隐式获取元素的位置。

回答by Denilson Amorim

Use the std::vector::frontand std::vector::backto get a referenceto the data in the first and last positions.

使用std::vector::frontstd::vector::back获取对第一个和最后一个位置中的数据的引用

Reference is a keyword here because you could efficiently check the address of your iterating itemand the address of the respective front/back references. In your example you take the itemby value not reference so this prehaps wouldn't work, take in consideration this example that'd work with this method:

Reference 在这里是一个关键字,因为您可以有效地检查迭代item的地址和相应的前/后引用的地址。在您的示例中,您采用的是itemby 值而不是引用,因此此 prehaps 不起作用,请考虑使用此方法的此示例:

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

If the object overloads the address of operator &(though it's considered a bad practice)you might want to use std::addressofinstead.

如果对象重载了运算符的地址&(尽管这被认为是一种不好的做法),您可能想std::addressof改用它。

This method won't work however for the std::vector<bool>specialization since it optimizes the vector to store booleans efficiently with bits, and since we cannot have references to bits, all references taken out this data structure is a proxy object not exactly tied to the address of the internal data.

然而,这种方法不适用于std::vector<bool>专业化,因为它优化了向量以有效地用位存储布尔值,并且由于我们不能引用位,所以从这个数据结构中取出的所有引用都是一个代理对象,并没有完全绑定到地址内部数据。

回答by R Sahu

Use std::vector::front()for the first element.
Use std::vector::back()for the last element.

使用std::vector::front()的第一个元素。
使用std::vector::back()最后一个元素。

Before you call those functions, make sure that the vectoris not empty.

在调用这些函数之前,请确保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

回答by iammilind

For value based comparison, you may use myVector.front()/myVector[0]as the first and myVector.back()/myVector[myVector.size()-1]as the last element.

对于基于值的比较,您可以使用myVector.front()/myVector[0]作为第一个元素和myVector.back()/myVector[myVector.size()-1]作为最后一个元素。

Suggestion
Capture the reference by default to avoid unwanted copies. e.g.

建议
默认情况下捕获参考以避免不需要的副本。例如

for(const auto& I : myVector)

for(const auto& I : myVector)

回答by isanae

You could search for it again, but that would be rather inefficient. If you need information on the position of the current item, you probably want to use an iterator or an index:

您可以再次搜索它,但这会相当低效。如果您需要有关当前项目位置的信息,您可能需要使用迭代器或索引:

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

回答by Dietr1ch

If you have special cases for the boundaries you should use the ol' iterator version, but separating the first and last cases away from the loop.

如果您有边界的特殊情况,您应该使用 ol' 迭代器版本,但将第一个和最后一个案例与循环分开。

If the cases share the code after that if you should encapsulate it on a function.

如果案例共享之后的代码,如果您应该将其封装在函数中。

I can't write code from my phone :c

我无法从手机上编写代码 :c

回答by jafox

This works for me

这对我有用

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

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

  if (&e != &vi.back())
    cout << ',';
}
cout << '}' << endl;