أي ما يعادل remove_if عن الأمراض المنقولة جنسيا :: خريطة

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

  •  03-07-2019
  •  | 
  •  

سؤال

وكنت أحاول أن يمحو مجموعة من العناصر من خريطة على أساس حالة معينة. كيف أفعل ذلك باستخدام خوارزميات STL؟

في البداية فكرت في استخدام remove_if ولكن من غير الممكن كما remove_if لا يعمل من أجل حاوية النقابي.

هل هناك أي "remove_if" خوارزمية يعادل التي تعمل على الخريطة؟

وكخيار بسيط، فكرت في حلقات من خلال الخريطة، ومحو. ولكن حلقات من خلال الخريطة، ومحو خيارا آمنا؟ (كما المكررات الحصول غير صالحة بعد محو)

واعتدت المثال التالي:

bool predicate(const std::pair<int,std::string>& x)
{
    return x.first > 2;
}

int main(void) 
{

    std::map<int, std::string> aMap;

    aMap[2] = "two";
    aMap[3] = "three";
    aMap[4] = "four";
    aMap[5] = "five";
    aMap[6] = "six";

//      does not work, an error
//  std::remove_if(aMap.begin(), aMap.end(), predicate);

    std::map<int, std::string>::iterator iter = aMap.begin();
    std::map<int, std::string>::iterator endIter = aMap.end();

    for(; iter != endIter; ++iter)
    {
            if(Some Condition)
            {
                            // is it safe ?
                aMap.erase(iter++);
            }
    }

    return 0;
}
هل كانت مفيدة؟

المحلول

وتقريبا.

for(; iter != endIter; ) {
            if (Some Condition) {
                    aMap.erase(iter++);
            } else {
                    ++iter;
            }
}

وماذا كنت قد أصلا أن زيادة المكرر <م> مرتين إذا فعلت محو عنصر من ذلك. هل يمكن أن يحتمل تخطي العناصر التي تحتاج إلى أن تمحى.

وهذا هو خوارزمية المشتركة رأيت المستخدمة وتوثيقها في العديد من الأماكن.

[تحرير] أنت صحيح أن المكررات ويبطل بعد محو، ولكن المكررات الوحيدة الرجوع إلى العنصر الذي يتم مسح، المكررات أخرى لا تزال سارية المفعول. ومن هنا باستخدام ++ ايتر في الدعوة محو ().

نصائح أخرى

erase_if عن الأمراض المنقولة جنسيا :: خريطة (وغيرها من الحاويات)

وأنا استخدم القالب التالي لهذا الشيء.

namespace stuff {
  template< typename ContainerT, typename PredicateT >
  void erase_if( ContainerT& items, const PredicateT& predicate ) {
    for( auto it = items.begin(); it != items.end(); ) {
      if( predicate(*it) ) it = items.erase(it);
      else ++it;
    }
  }
}

وهذا لن يعود أي شيء، ولكن سيتم إزالة العناصر من الأمراض المنقولة جنسيا :: الخريطة.

والاستخدام سبيل المثال:

// 'container' could be a std::map
// 'item_type' is what you might store in your container
using stuff::erase_if;
erase_if(container, []( item_type& item ) {
  return /* insert appropriate test */;
});

والمثال الثاني (يسمح لك بالمرور في قيمة الاختبار):

// 'test_value' is value that you might inject into your predicate.
// 'property' is just used to provide a stand-in test
using stuff::erase_if;
int test_value = 4;  // or use whatever appropriate type and value
erase_if(container, [&test_value]( item_type& item ) {
  return item.property < test_value;  // or whatever appropriate test
});

وحصلت على هذه الوثائق من ممتاز SGI STL إشارة :

<اقتباس فقرة>   

وخريطة لديه خاصية هامة   إدخال عنصر جديد إلى خريطة   لا ينقض المكررات أن   تشير إلى عناصر القائمة. ومحو   لا أيضا عنصر من الخريطة لا   إبطال أي التكرارات، ما عدا،   بطبيعة الحال، لالمكررات أن الواقع   أشر إلى العنصر الذي يجري   تمحى.

ويبطل إرادة لذا، فإن مكرر لديك الذي لافتا في عنصر لتمحى بالطبع. تفعل شيئا مثل هذا:

if (some condition)
{
  iterator here=iter++;
  aMap.erase(here)
}

والرمز الأصلي ديه قضية واحدة فقط:

for(; iter != endIter; ++iter)
{
    if(Some Condition)
    {
        // is it safe ?
        aMap.erase(iter++);
    }
}

وهنا يتزايد iter مرة واحدة في لحلقة ووقت آخر في محو، والتي سوف الارجح في نهاية المطاف في بعض حلقة لا نهائية.

والآن، std::experimental::erase_if متاح في <experimental/map> الرأس.

وانظر: http://en.cppreference.com/w/cpp / تجريبية / خريطة / erase_if

ومن الملاحظات أسفل:

http://www.sgi.com/tech/stl/PairAssociativeContainer.html

وعلى الجمعياتي الحاويات زوج لا يمكن أن توفر المكررات قابلة للتغيير (كما هو موضح في متطلبات تافهة مكرر)، لأن نوع قيمة مكرر قابلة للتغيير يجب أن يكون احالة، والزوج ليس احالة. ومع ذلك، يمكن الجمعياتي الحاويات زوج توفير المكررات التي ليست تماما ثابتة: المكررات مثل أن تعبير (* ط) .second = d غير صالح.

أولا

<اقتباس فقرة>   

وخريطة لديه خاصية هامة أن إدخال عنصر جديد إلى خريطة لا يفسد المكررات التي تشير إلى عناصر القائمة. محو عنصر من الخريطة أيضا لا يبطل أي التكرارات، ما عدا، بالطبع، لالمكررات التي تشير في الواقع إلى العنصر الذي يتم مسحها.

والثانية، رمز التالي هو جيد

for(; iter != endIter; )
{
    if(Some Condition)
    {
        aMap.erase(iter++);
    }
    else
    {
        ++iter;
    }
}

عند استدعاء دالة، يتم تقييم المعلمات قبل استدعاء هذه الوظيفة.

وهكذا عندما ايتر ++ يتم تقييم قبل الدعوة لمحو، المشغل ++ من مكرر سيعود العنصر الحالي وسوف يشير إلى العنصر التالي بعد المكالمة.

وIMHO لا يوجد ما يعادل remove_if().
لا يمكنك إعادة ترتيب الخريطة.
حتى remove_if() لا يمكن وضع الخاص بك زوجا من الفائدة في نهاية التي يمكنك الاتصال erase().

وبناء على الحديد المخلص الجواب بالنسبة لأولئك الذين يرغبون في تقديم مجموعة أكثر على غرار المكررات الأمراض المنقولة جنسيا وظيفية مع الأخذ .

template< typename ContainerT, class _FwdIt, class _Pr >
void erase_if(ContainerT& items, _FwdIt it, _FwdIt _Last, _Pr _Pred) {
    for (; it != _Last; ) {
        if (_Pred(*it)) it = items.erase(it);
        else ++it;
    }
}

والغريب إذا كان هناك بعض وسيلة لانقاص البنود ContainerT والحصول على هذا من التكرار.

الجواب

ستيف الحماقة في أشعر أكثر كفاءة.

وهنا آخر على سهل ولكن أقل حل فعال : ل

والحل يستخدم remove_copy_if لنسخ القيم نريد في وعاء جديد، ثم مقايضة محتويات الحاوية الأصلية مع تلك من جديد واحد:

std::map<int, std::string> aMap;

...
//Temporary map to hold the unremoved elements
std::map<int, std::string> aTempMap;

//copy unremoved values from aMap to aTempMap
std::remove_copy_if(aMap.begin(), aMap.end(), 
                    inserter(aTempMap, aTempMap.end()),
                    predicate);

//Swap the contents of aMap and aTempMap
aMap.swap(aTempMap);

إذا كنت تريد محو كل العناصر مع مفتاح أكبر من 2، ثم أن أفضل طريقة هي

map.erase(map.upper_bound(2), map.end());

ويعمل فقط لنطاقات الرغم من ذلك، ليس من أجل أي المسند.

ويمكنني استخدام مثل هذا

 std::map<int, std::string> users;    
 for(auto it = users.begin(); it <= users.end()) {
    if(<condition>){
      it = users.erase(it);
    } else {
    ++it;
    }
 }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top