[array] add RemoveAllMatching() (#7829)

This commit adds a new method in `Array` to remove all elements
in the array matching a given indicator.

This commit also updates `test_array.cpp` unit test to validate
the behavior of the newly added method.
This commit is contained in:
Abtin Keshavarzian
2022-06-23 07:35:28 -07:00
committed by GitHub
parent 5cfbcfcbf4
commit dff9111d0c
2 changed files with 124 additions and 1 deletions
+36
View File
@@ -477,6 +477,42 @@ public:
}
}
/**
* This template method removes all elements in the array matching a given indicator.
*
* This method behaves similar to `Remove()`, i.e., a matched element is replaced with the last element in the
* array (using `=` operator on `Type`). So the order of items in the array can change after a call to this method.
*
* The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements
* in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each
* `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly:
*
* bool Type::Matches(const Indicator &aIndicator) const
*
* @param[in] aIndicator An indicator to match with elements in the array.
*
*/
template <typename Indicator> void RemoveAllMatching(const Indicator &aIndicator)
{
for (IndexType index = 0; index < GetLength();)
{
Type &entry = mElements[index];
if (entry.Matches(aIndicator))
{
Remove(entry);
// When the entry is removed from the array it is
// replaced with the last element. In this case, we do
// not increment `index`.
}
else
{
index++;
}
}
}
/**
* This method overloads assignment `=` operator to copy elements from another array into the array.
*
+88 -1
View File
@@ -176,6 +176,14 @@ void TestArrayCopyAndFindMatching(void)
{
constexpr uint16_t kMaxSize = 10;
enum MatchMode : uint8_t
{
kMatchAll,
kMatchNone,
kMatchOddYear,
kMatchEvenYear,
};
struct Entry : public Unequatable<Entry>
{
Entry(void) = default;
@@ -190,12 +198,44 @@ void TestArrayCopyAndFindMatching(void)
bool Matches(const char *aName) const { return strcmp(aName, mName) == 0; }
bool Matches(uint16_t aYear) const { return aYear == mYear; }
bool Matches(MatchMode aMatchMode) const
{
bool matches = false;
switch (aMatchMode)
{
case kMatchAll:
matches = true;
break;
case kMatchNone:
matches = false;
break;
case kMatchOddYear:
matches = ((mYear % 2) != 0);
break;
case kMatchEvenYear:
matches = ((mYear % 2) == 0);
break;
}
return matches;
}
const char *mName;
uint16_t mYear;
};
static const MatchMode kMatchModes[] = {kMatchAll, kMatchNone, kMatchEvenYear, kMatchOddYear};
static const char *kMatchModeStrings[] = {
"kMatchAll",
"kMatchNone",
"kMatchOddYear",
"kMatchEvenYear",
};
Entry ps1("PS", 1994);
Entry ps2("PS2", 2000);
Entry ps2("PS2", 1999);
Entry ps3("PS3", 2006);
Entry ps4("PS4", 2013);
Entry ps5("PS5", 2020);
@@ -300,6 +340,7 @@ void TestArrayCopyAndFindMatching(void)
array2 = array1;
array2.RemoveMatching(entryToRemove.mName);
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - ");
printf("\nArray after `RemoveMatching()` on entry %s\n", entryToRemove.mName);
VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
@@ -315,6 +356,52 @@ void TestArrayCopyAndFindMatching(void)
array2.RemoveMatching(entryToRemove.mName);
VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
// Test `RemoveAllMatching()` removing a single matching entry.
array2 = array1;
array2.RemoveAllMatching(entryToRemove.mName);
VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
for (const Entry &entry : array2)
{
VerifyOrQuit(entry != entryToRemove);
VerifyOrQuit(array1.Contains(entry));
}
array2.RemoveAllMatching(entryToRemove.mName);
VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
// Test `RemoveAllMatching()` using different match modes
// removing different subsets.
for (MatchMode matchMode : kMatchModes)
{
array3 = array2;
array3.RemoveAllMatching(matchMode);
printf("\nArray after `RemoveAllMatching(%s)\n", kMatchModeStrings[matchMode]);
for (const Entry &entry : array3)
{
VerifyOrQuit(!entry.Matches(matchMode));
VerifyOrQuit(array2.Contains(entry));
printf("- Name:%-3s Year:%d\n", entry.mName, entry.mYear);
}
for (const Entry &entry : array2)
{
if (!entry.Matches(matchMode))
{
VerifyOrQuit(array2.Contains(entry));
}
}
array3.RemoveAllMatching(kMatchAll);
VerifyOrQuit(array3.IsEmpty());
}
}
printf("\n");