AK: Add HashTable::remove_all_matching(predicate)

This removes all matching entries from a table in a single pass.
This commit is contained in:
Andreas Kling 2022-01-05 16:45:42 +01:00
parent 365bd8a0c3
commit 54cf42fac1
2 changed files with 37 additions and 1 deletions

View file

@ -384,7 +384,7 @@ public:
return false;
}
void remove(Iterator iterator)
Iterator remove(Iterator iterator)
{
VERIFY(iterator.m_bucket);
auto& bucket = *iterator.m_bucket;
@ -394,6 +394,9 @@ public:
if constexpr (!IsOrdered)
VERIFY(!bucket.end);
auto next_iterator = iterator;
++next_iterator;
bucket.slot()->~T();
bucket.used = false;
bucket.deleted = true;
@ -411,6 +414,19 @@ public:
else
m_collection_data.tail = bucket.previous;
}
return next_iterator;
}
template<typename TUnaryPredicate>
void remove_all_matching(TUnaryPredicate predicate)
{
for (auto it = begin(); it != end();) {
if (predicate(*it))
it = remove(it);
else
++it;
}
}
private:

View file

@ -84,6 +84,26 @@ TEST_CASE(table_remove)
EXPECT(strings.find("Two") != strings.end());
}
TEST_CASE(table_remove_all_matching)
{
HashTable<int> ints;
ints.set(1);
ints.set(2);
ints.set(3);
ints.set(4);
EXPECT_EQ(ints.size(), 4u);
ints.remove_all_matching([&](int value) { return value > 2; });
EXPECT_EQ(ints.size(), 2u);
ints.remove_all_matching([&](int) { return true; });
EXPECT(ints.is_empty());
}
TEST_CASE(case_insensitive)
{
HashTable<String, CaseInsensitiveStringTraits> casetable;