[llvm] r213090 - ADT: Add MapVector::remove_if

Duncan P. N. Exon Smith dexonsmith at apple.com
Tue Jul 15 13:24:59 PDT 2014


Author: dexonsmith
Date: Tue Jul 15 15:24:56 2014
New Revision: 213090

URL: http://llvm.org/viewvc/llvm-project?rev=213090&view=rev
Log:
ADT: Add MapVector::remove_if

Add a `MapVector::remove_if()` that erases items in bulk in linear time,
as opposed to quadratic time for repeated calls to `MapVector::erase()`.

Modified:
    llvm/trunk/docs/ProgrammersManual.rst
    llvm/trunk/include/llvm/ADT/MapVector.h
    llvm/trunk/unittests/ADT/MapVectorTest.cpp

Modified: llvm/trunk/docs/ProgrammersManual.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ProgrammersManual.rst?rev=213090&r1=213089&r2=213090&view=diff
==============================================================================
--- llvm/trunk/docs/ProgrammersManual.rst (original)
+++ llvm/trunk/docs/ProgrammersManual.rst Tue Jul 15 15:24:56 2014
@@ -1441,8 +1441,10 @@ order, making it an easy (but somewhat e
 iteration over maps of pointers.
 
 It is implemented by mapping from key to an index in a vector of key,value
-pairs.  This provides fast lookup and iteration, but has two main drawbacks: The
-key is stored twice and removing elements takes linear time.
+pairs.  This provides fast lookup and iteration, but has two main drawbacks:
+the key is stored twice and removing elements takes linear time.  If it is
+necessary to remove elements, it's best to remove them in bulk using
+``remove_if()``.
 
 .. _dss_inteqclasses:
 

Modified: llvm/trunk/include/llvm/ADT/MapVector.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/MapVector.h?rev=213090&r1=213089&r2=213090&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/MapVector.h (original)
+++ llvm/trunk/include/llvm/ADT/MapVector.h Tue Jul 15 15:24:56 2014
@@ -146,8 +146,36 @@ public:
     }
     return Next;
   }
+
+  /// \brief Remove the elements that match the predicate.
+  ///
+  /// Erase all elements that match \c Pred in a single pass.  Takes linear
+  /// time.
+  template <class Predicate> void remove_if(Predicate Pred);
 };
 
+template <typename KeyT, typename ValueT, typename MapType, typename VectorType>
+template <class Function>
+void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) {
+  auto O = Vector.begin();
+  for (auto I = O, E = Vector.end(); I != E; ++I) {
+    if (Pred(*I)) {
+      // Erase from the map.
+      Map.erase(I->first);
+      continue;
+    }
+
+    if (I != O) {
+      // Move the value and update the index in the map.
+      *O = std::move(*I);
+      Map[O->first] = O - Vector.begin();
+    }
+    ++O;
+  }
+  // Erase trailing entries in the vector.
+  Vector.erase(O, Vector.end());
+}
+
 } // end namespace llvm
 
 #endif

Modified: llvm/trunk/unittests/ADT/MapVectorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/MapVectorTest.cpp?rev=213090&r1=213089&r2=213090&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/MapVectorTest.cpp (original)
+++ llvm/trunk/unittests/ADT/MapVectorTest.cpp Tue Jul 15 15:24:56 2014
@@ -68,3 +68,24 @@ TEST(MapVectorTest, erase) {
   ASSERT_EQ(MV[3], 4);
   ASSERT_EQ(MV[5], 6);
 }
+
+TEST(MapVectorTest, remove_if) {
+  MapVector<int, int> MV;
+
+  MV.insert(std::make_pair(1, 11));
+  MV.insert(std::make_pair(2, 12));
+  MV.insert(std::make_pair(3, 13));
+  MV.insert(std::make_pair(4, 14));
+  MV.insert(std::make_pair(5, 15));
+  MV.insert(std::make_pair(6, 16));
+  ASSERT_EQ(MV.size(), 6u);
+
+  MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; });
+  ASSERT_EQ(MV.size(), 3u);
+  ASSERT_EQ(MV.find(1), MV.end());
+  ASSERT_EQ(MV.find(3), MV.end());
+  ASSERT_EQ(MV.find(5), MV.end());
+  ASSERT_EQ(MV[2], 12);
+  ASSERT_EQ(MV[4], 14);
+  ASSERT_EQ(MV[6], 16);
+}





More information about the llvm-commits mailing list