كيف يمكنني إزالة عنصر من المحكمة ناقلات مع قيمة معينة ؟
سؤال
كنت أبحث في API وثائق المحكمة ناقلات, و لاحظت لا يوجد طريقة على ناقلات الدرجة التي سمحت إزالة عنصر مع قيمة معينة.هذا يبدو وكأنه عملية مشتركة ، ويبدو من الغريب أن هناك أي طريقة للقيام بذلك.
المحلول
std::remove
لا فعلا محو عنصر من الحاوية ، ولكنه يعود نهاية جديدة مكرر والتي يمكن أن تنتقل إلى container_type::erase
للقيام الحقيقي إزالة العناصر الإضافية التي هي الآن في نهاية الحاوية:
std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());
نصائح أخرى
إذا كنت ترغب في إزالة وهو البند التالي سوف يكون قليلا أكثر كفاءة.
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
v.erase(it);
أو قد تجنب النفقات العامة من تحريك العناصر إذا كان النظام لا يهم لك:
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if (it != v.end()) {
using std::swap;
// swap the one to be removed with the last element
// and remove the item at the end of the container
// to prevent moving all items after '5' by one
swap(*it, v.back());
v.pop_back();
}
استخدام العالمية طريقة std::إزالة مع begin و end مكرر ، ومن ثم استخدام std::المتجهات.محو فعلا إزالة العناصر.
توثيق الروابط
الأمراض المنقولة جنسيا::إزالة http://www.cppreference.com/cppalgorithm/remove.html
الأمراض المنقولة جنسيا::المتجهات.محو http://www.cppreference.com/cppvector/erase.html
std::vector<int> v;
v.push_back(1);
v.push_back(2);
//Vector should contain the elements 1, 2
//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);
//Erase the "removed" elements.
v.erase(newEnd, v.end());
//Vector should now only contain 2
بفضل جيم باك لافتا خطأ بلدي.
إجابات أخرى تغطي كيفية القيام بذلك بشكل جيد, ولكن فكرت أيضا أن أشير إلى أنه ليس من الغريب أن هذا ليس في ناقلات API:انها غير فعالة, البحث الخطي من خلال ناقلات قيمة ، تليها مجموعة من النسخ إلى إزالته.
إذا كنت تفعل هذه العملية بشكل مكثف ، فإنه يمكن أن يكون من المفيد النظر في std::مجموعة بدلا من ذلك لهذا السبب.
إذا كان لديك لم يتم فرزها ناقلات, ثم يمكنك ببساطة مبادلة مع آخر ناقلات العنصر ثم resize()
.
مع أمر الحاوية سوف تكون أفضل حالا مع std::vector::erase()
.علما أن هناك std::remove()
المحددة في <algorithm>
, ولكن هذا في الواقع لا تفعل محو.(قراءة الوثائق بعناية).
أقصر الحل (الذي لا يجبرك على تكرار اسم ناقلات 4 مرات) سيكون لاستخدام دفعة:
#include <boost/range/algorithm_ext/erase.hpp>
// ...
boost::remove_erase(vec, int_to_remove);
انظر أيضا الأمراض المنقولة جنسيا::remove_if أن تكون قادرة على استخدام المسند...
هنا مثال من الرابط أعلاه:
vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 4 2 8 5 7"
vector<int>::iterator new_end =
remove_if(V.begin(), V.end(),
compose1(bind2nd(equal_to<int>(), 0),
bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 5 7".
من c++20:
غير دالة عضو قدم std::erase
, الذي يأخذ ناقلات القيمة إلى إزالتها كما المدخلات.
مثلا:
std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);
إذا كنت تريد أن تفعل ذلك دون أي إضافية تشمل ما يلي:
vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
IComponent* juggler;
if (componentToRemove != NULL)
{
for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
{
if (componentToRemove == myComponents[currComponentIndex])
{
//Since we don't care about order, swap with the last element, then delete it.
juggler = myComponents[currComponentIndex];
myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
myComponents[myComponents.size() - 1] = juggler;
//Remove it from memory and let the vector know too.
myComponents.pop_back();
delete juggler;
}
}
}
}
اثنين من الطرق المتوفرة التي يمكنك استخدامها لمسح عنصر بشكل خاص.دعونا نلقي ناقلات
std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);
1) عدم كفاءة الطريقة : على الرغم من أنه يبدو أن تكون فعالة جدا ولكن ليس بسبب محو وظيفة delets عناصر والتحولات جميع العناصر نحو اليسار بمقدار 1.حتى تعقيدها سيتم O(n^2)
std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
if(*itr == value)
{
v.erase(itr);
}
else
++itr;
}
2) كفاءة ( مستحسن ) :كما هو معروف محو - إزالة التعابير .
- الأمراض المنقولة جنسيا::إزالة يحول نطاق معين في مجموعة مع جميع العناصر التي تقارن لا يساوي عنصر معين تحولت إلى بداية الحاوية.
- في الواقع لا إزالة مطابقة العناصر.فقط تحول غير مطابقة ابتداء ويعطي مكرر جديدة صالحة الغاية.فإنه يتطلب فقط O(n) التعقيد.
الناتج من إزالة الخوارزمية :
10 20 30 50 40 50
كما عودة نوع من إزالة التكرار الجديد نهاية هذا النطاق.
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);
الآن استخدام ناقلات محو وظيفة حذف عناصر من نهاية إلى نهاية العمر الوسيط.فإنه يتطلب O(1) مرة.
v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );
لذلك هذه الطريقة في العمل O(n)