cmAlgorithms: Add cmRemoveDuplicates algorithm.
Start by creating a vector to hold a unique values of the input range. We expect that in most cases, there will be relatively few duplicates, so reserving enough memory for a complete copy is worthwhile. Unlike a solution involving a std::set, this algorithm allocates all the memory it needs in one go and in one place, so it is more cache friendly. Populate the unique copy with a lower_bound insert algorithm and record the indices of duplicates. This is the same complexity as the std::set insert algorithm, but without the need to allocate memory on the heap and other disadvantages of std::set. Remove the duplicates with the cmRemoveIndices algorithm.
This commit is contained in:
parent
3cfe7a4ca8
commit
cebeed2486
@ -250,4 +250,33 @@ typename Range::const_iterator cmRemoveMatching(Range &r, MatchRange const& m)
|
|||||||
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
|
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Range>
|
||||||
|
typename Range::const_iterator cmRemoveDuplicates(Range& r)
|
||||||
|
{
|
||||||
|
std::vector<typename Range::value_type> unique;
|
||||||
|
unique.reserve(r.size());
|
||||||
|
std::vector<size_t> indices;
|
||||||
|
size_t count = 0;
|
||||||
|
for(typename Range::const_iterator it = r.begin();
|
||||||
|
it != r.end(); ++it, ++count)
|
||||||
|
{
|
||||||
|
typename Range::iterator low =
|
||||||
|
std::lower_bound(unique.begin(), unique.end(), *it);
|
||||||
|
if (low == unique.end() || *low != *it)
|
||||||
|
{
|
||||||
|
unique.insert(low, *it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
indices.push_back(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (indices.empty())
|
||||||
|
{
|
||||||
|
return r.end();
|
||||||
|
}
|
||||||
|
std::sort(indices.begin(), indices.end());
|
||||||
|
return cmRemoveIndices(r, indices);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user