Проверьте, является ли элемент первым или последним в 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::
way для проверки первого и последнего элемента?
Ответы
Ответ 1
В этом случае вы не должны использовать 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
на основе диапазона без дополнительного индекса, который отслеживает, где именно находится вектор.
РЕДАКТИРОВАТЬ См. также @thelink2012 ответ на вопрос о том, как "обмануть" ваш for
на основе диапазона, чтобы вы могли нести позицию элемента неявно.
Ответ 2
Используйте std::vector::front
и std::vector::back
, чтобы получить ссылку к данным в первой и последней позициях.
Ссылка - это ключевое слово здесь, потому что вы могли бы эффективно проверить адрес вашего итерации 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>
, поскольку он оптимизирует вектор для эффективного хранения логических данных с битами, и поскольку мы не можем иметь ссылки на биты, все ссылки, извлеченные из этой структуры данных, являются прокси-объектами не точно привязаны к адресу внутренних данных.
Ответ 3
Используйте 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
Ответ 4
Для сравнения на основе значения вы можете использовать myVector.front()
/myVector[0]
как первый и myVector.back()
/myVector[myVector.size()-1]
в качестве последнего элемента.
Предложение
Захватите ссылку по умолчанию, чтобы избежать нежелательных копий. например.
for(const auto& I : myVector)
Ответ 5
Вы можете искать его снова, но это было бы довольно неэффективно. Если вам нужна информация о позиции текущего элемента, вы, вероятно, захотите использовать итератор или индекс:
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;
}
Ответ 6
Если у вас есть особые случаи для границ, вы должны использовать версию olтератора, но отделяя первый и последний случаи от цикла.
Если случаи передают код после этого, если вы должны инкапсулировать его в функцию.
Я не могу написать код с моего телефона: c
Ответ 7
Это работает для меня
vector<int> vi {1,2,3,4};
cout << "vi = {";
for (const auto &e : vi) {
cout << e;
if (&e != &vi.back())
cout << ',';
}
cout << '}' << endl;
Ответ 8
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;
Это не сработает, поскольку третий символ совпадает с последним символом.