From 376e5ef9125fcc7c17c2b96f14cb4b64b28e191a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 5 Jan 2022 16:53:24 +0100 Subject: [PATCH] AK: Add HashMap::remove_all_matching(predicate) This removes all matching entries from a hash map in a single pass. --- AK/HashMap.h | 15 +++++++++++++-- Tests/AK/TestHashMap.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/AK/HashMap.h b/AK/HashMap.h index 33251fde72..8a7d2f3160 100644 --- a/AK/HashMap.h +++ b/AK/HashMap.h @@ -74,6 +74,17 @@ public: return false; } + template + void remove_all_matching(TUnaryPredicate predicate) + { + for (auto it = begin(); it != end();) { + if (predicate(it->key, it->value)) + it = remove(it); + else + ++it; + } + } + using HashTableType = HashTable; using IteratorType = typename HashTableType::Iterator; using ConstIteratorType = typename HashTableType::ConstIterator; @@ -180,9 +191,9 @@ public: return find(value) != end(); } - void remove(IteratorType it) + IteratorType remove(IteratorType it) { - m_table.remove(it); + return m_table.remove(it); } V& ensure(const K& key) diff --git a/Tests/AK/TestHashMap.cpp b/Tests/AK/TestHashMap.cpp index 86fc4e98d9..9fef97d8e9 100644 --- a/Tests/AK/TestHashMap.cpp +++ b/Tests/AK/TestHashMap.cpp @@ -71,6 +71,30 @@ TEST_CASE(map_remove) EXPECT(number_to_string.find(2) != number_to_string.end()); } +TEST_CASE(remove_all_matching) +{ + HashMap map; + + map.set(1, "One"); + map.set(2, "Two"); + map.set(3, "Three"); + map.set(4, "Four"); + + EXPECT_EQ(map.size(), 4u); + + map.remove_all_matching([&](int key, String const& value) { + return key == 1 || value == "Two"; + }); + + EXPECT_EQ(map.size(), 2u); + EXPECT(map.contains(3)); + EXPECT(map.contains(4)); + + map.remove_all_matching([&](int, String const&) { return true; }); + + EXPECT(map.is_empty()); +} + TEST_CASE(case_insensitive) { HashMap casemap;