Add unique

This commit is contained in:
Roland Reichwein 2026-03-09 17:40:13 +01:00
parent b0bf06b9dd
commit fa0dfd7631
2 changed files with 178 additions and 0 deletions

View File

@ -2352,6 +2352,61 @@ namespace etl
return first;
}
//***************************************************************************
/// unique
/// see https://en.cppreference.com/w/cpp/algorithm/unique
///\ingroup algorithm
//***************************************************************************
template <typename TIterator>
ETL_CONSTEXPR14
TIterator unique(TIterator first, TIterator last)
{
if (first == last)
{
return last;
}
TIterator result = first;
while (++first != last)
{
if (!(*result == *first) && (++result != first))
{
*result = ETL_MOVE(*first);
}
}
return ++result;
}
//***************************************************************************
/// unique
/// see https://en.cppreference.com/w/cpp/algorithm/unique
/// predicate overload to determine equality.
///\ingroup algorithm
//***************************************************************************
template <typename TIterator, typename TBinaryPredicate>
ETL_CONSTEXPR14
TIterator unique(TIterator first, TIterator last, TBinaryPredicate predicate)
{
if (first == last)
{
return last;
}
TIterator result = first;
while (++first != last)
{
if (!predicate(*result, *first) && (++result != first))
{
*result = ETL_MOVE(*first);
}
}
return ++result;
}
}
//*****************************************************************************

View File

@ -3264,6 +3264,129 @@ namespace
CHECK(is_same);
}
//*************************************************************************
TEST(unique)
{
std::array<int, 10> data = { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5 };
std::array<int, 5> expected = { 1, 2, 3, 4, 5 };
auto end = etl::unique(data.begin(), data.end());
CHECK_EQUAL(5, std::distance(data.begin(), end));
bool is_same = std::equal(expected.begin(), expected.end(), data.begin());
CHECK(is_same);
}
//*************************************************************************
TEST(unique_empty_range)
{
std::array<int, 0> data = {};
auto end = etl::unique(data.begin(), data.end());
CHECK(end == data.end());
}
//*************************************************************************
TEST(unique_single_element)
{
std::array<int, 1> data = { 42 };
std::array<int, 1> expected = { 42 };
auto end = etl::unique(data.begin(), data.end());
CHECK_EQUAL(1, std::distance(data.begin(), end));
bool is_same = std::equal(expected.begin(), expected.end(), data.begin());
CHECK(is_same);
}
//*************************************************************************
TEST(unique_no_duplicates)
{
std::array<int, 5> data = { 1, 2, 3, 4, 5 };
std::array<int, 5> expected = { 1, 2, 3, 4, 5 };
auto end = etl::unique(data.begin(), data.end());
CHECK_EQUAL(5, std::distance(data.begin(), end));
bool is_same = std::equal(expected.begin(), expected.end(), data.begin());
CHECK(is_same);
}
//*************************************************************************
TEST(unique_all_same)
{
std::array<int, 5> data = { 7, 7, 7, 7, 7 };
std::array<int, 1> expected = { 7 };
auto end = etl::unique(data.begin(), data.end());
CHECK_EQUAL(1, std::distance(data.begin(), end));
bool is_same = std::equal(expected.begin(), expected.end(), data.begin());
CHECK(is_same);
}
//*************************************************************************
TEST(unique_with_predicate)
{
std::array<int, 10> data = { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5 };
std::array<int, 5> expected = { 1, 2, 3, 4, 5 };
auto end = etl::unique(data.begin(), data.end(), std::equal_to<int>());
CHECK_EQUAL(5, std::distance(data.begin(), end));
bool is_same = std::equal(expected.begin(), expected.end(), data.begin());
CHECK(is_same);
}
//*************************************************************************
TEST(unique_with_predicate_custom)
{
// Group elements that are close to each other (differ by less than 3)
std::array<int, 8> data = { 1, 2, 3, 7, 8, 9, 20, 21 };
std::array<int, 3> expected = { 1, 7, 20 };
auto end = etl::unique(data.begin(), data.end(), [](int a, int b) { return (b - a) < 3; });
CHECK_EQUAL(3, std::distance(data.begin(), end));
bool is_same = std::equal(expected.begin(), expected.end(), data.begin());
CHECK(is_same);
}
//*************************************************************************
TEST(unique_matches_std)
{
std::array<int, 12> data1 = { 1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 5 };
std::array<int, 12> data2 = data1;
auto std_end = std::unique(data1.begin(), data1.end());
auto etl_end = etl::unique(data2.begin(), data2.end());
size_t std_size = std::distance(data1.begin(), std_end);
size_t etl_size = std::distance(data2.begin(), etl_end);
CHECK_EQUAL(std_size, etl_size);
bool is_same = std::equal(data1.begin(), std_end, data2.begin());
CHECK(is_same);
}
//*************************************************************************
TEST(unique_with_predicate_matches_std)
{
std::array<int, 12> data1 = { 1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 5 };
std::array<int, 12> data2 = data1;
auto std_end = std::unique(data1.begin(), data1.end(), std::equal_to<int>());
auto etl_end = etl::unique(data2.begin(), data2.end(), std::equal_to<int>());
size_t std_size = std::distance(data1.begin(), std_end);
size_t etl_size = std::distance(data2.begin(), etl_end);
CHECK_EQUAL(std_size, etl_size);
bool is_same = std::equal(data1.begin(), std_end, data2.begin());
CHECK(is_same);
}
//*************************************************************************
struct generator
{