Ref T464 Implement removal of one sequence from another in O(n),

assuming that elements in both sequences are in the same order in both.
This commit is contained in:
Mat Sutcliffe
2018-12-11 17:12:09 +00:00
committed by Klaus Basan
parent 40ae7174a7
commit 71de01065b
4 changed files with 47 additions and 4 deletions

View File

@@ -340,10 +340,7 @@ namespace BlackGui
else
{
ContainerType unselectedObjects(container());
for (const ObjectType &obj : selected)
{
unselectedObjects.remove(obj);
}
unselectedObjects.removeIfInSubset(selected);
this->updateContainerMaybeAsync(unselectedObjects);
delta = currentRows - unselectedObjects.size();
}

View File

@@ -22,6 +22,27 @@
namespace BlackMisc
{
/*!
* Removes those elements in range 1 that appear also in range 2 leaving only those that
* do not appear in range 2. Returns an iterator one past the new end of range 1.
* \pre All the elements of range 2 must be present in the same order in range 1.
*/
template <typename I, typename J>
auto removeIfIn(I begin1, I end1, J begin2, J end2)
{
auto newEnd = end1;
std::for_each(begin2, end2, [&](const auto &rm)
{
const auto found = std::find(begin1, end1, rm);
Q_ASSERT(found != end1);
if (newEnd == end1) { newEnd = found; }
else { newEnd = std::move(begin1, found, newEnd); }
begin1 = std::next(found);
});
if (newEnd != end1) { newEnd = std::move(begin1, end1, newEnd); }
return newEnd;
}
namespace Private
{
//! \private A high quality deterministic pseudo-random number generator.

View File

@@ -321,6 +321,13 @@ namespace BlackMisc
return removeIf([&other](const T &v) { return other.contains(v); });
}
//! Remove all elements if they are in other
//! \pre All elements of other must be present in the same order in this.
void removeIfInSubset(const CSequence &other)
{
erase(BlackMisc::removeIfIn(begin(), end(), other.begin(), other.end()), end());
}
//! Replace elements matching the given element with a replacement.
//! \return The number of elements replaced.
int replace(const T &original, const T &replacement)

View File

@@ -65,6 +65,7 @@ namespace BlackMiscTest
void joinAndSplit();
void findTests();
void sortTests();
void removeTests();
void dictionaryBasics();
void timestampList();
void offsetTimestampList();
@@ -199,6 +200,23 @@ namespace BlackMiscTest
QVERIFY2(list.sortedBy(&Person::getAge, &Person::getName) == sorted, "sort by multiple members");
}
void CTestContainers::removeTests()
{
const CSequence<int> base { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const CSequence<CSequence<int>> subsets
{
{}, { 1 }, { 9 }, { 5 }, { 1, 9 }, { 1, 5 }, { 5, 9 }, { 1, 2 },
{ 8, 9 }, { 4, 5, 6 }, { 1, 5, 9 }, { 3, 7 }, { 3, 5, 7 }, base
};
for (const auto &subset : subsets)
{
auto copy1 = base, copy2 = base;
copy1.removeIfIn(subset);
copy2.removeIfInSubset(subset);
QVERIFY2(copy1 == copy2, "removeIfInSubset");
}
}
void CTestContainers::dictionaryBasics()
{
CTestValueObject key1("Key1", "This is key object 1");