كيف يمكنني إزالة عنصر من المحكمة ناقلات مع قيمة معينة ؟

StackOverflow https://stackoverflow.com/questions/39912

  •  09-06-2019
  •  | 
  •  

سؤال

كنت أبحث في 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);

انظر http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html

انظر أيضا الأمراض المنقولة جنسيا::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)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top