mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Add unique_copy
This commit is contained in:
parent
fa0dfd7631
commit
12773f1f43
@ -2407,6 +2407,70 @@ namespace etl
|
||||
|
||||
return ++result;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// unique_copy
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/unique_copy
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator, typename TOutputIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TOutputIterator unique_copy(TInputIterator first,
|
||||
TInputIterator last,
|
||||
TOutputIterator d_first)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return d_first;
|
||||
}
|
||||
|
||||
typename etl::iterator_traits<TInputIterator>::value_type prev = *first;
|
||||
*d_first = prev;
|
||||
|
||||
while (++first != last)
|
||||
{
|
||||
if (!(prev == *first))
|
||||
{
|
||||
prev = *first;
|
||||
*(++d_first) = prev;
|
||||
}
|
||||
}
|
||||
|
||||
return ++d_first;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// unique_copy
|
||||
/// see https://en.cppreference.com/w/cpp/algorithm/unique_copy
|
||||
/// predicate overload to determine equality.
|
||||
///\ingroup algorithm
|
||||
//***************************************************************************
|
||||
template <typename TInputIterator, typename TOutputIterator, typename TBinaryPredicate>
|
||||
ETL_CONSTEXPR14
|
||||
TOutputIterator unique_copy(TInputIterator first,
|
||||
TInputIterator last,
|
||||
TOutputIterator d_first,
|
||||
TBinaryPredicate predicate)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return d_first;
|
||||
}
|
||||
|
||||
typename etl::iterator_traits<TInputIterator>::value_type prev = *first;
|
||||
*d_first = prev;
|
||||
|
||||
while (++first != last)
|
||||
{
|
||||
if (!predicate(prev, *first))
|
||||
{
|
||||
prev = *first;
|
||||
*(++d_first) = prev;
|
||||
}
|
||||
}
|
||||
|
||||
return ++d_first;
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
@ -3387,6 +3387,152 @@ namespace
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy)
|
||||
{
|
||||
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 };
|
||||
std::array<int, 10> result = {};
|
||||
|
||||
auto end = etl::unique_copy(data.begin(), data.end(), result.begin());
|
||||
|
||||
CHECK_EQUAL(5, std::distance(result.begin(), end));
|
||||
bool is_same = std::equal(expected.begin(), expected.end(), result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_empty_range)
|
||||
{
|
||||
std::array<int, 0> data = {};
|
||||
std::array<int, 1> result = { 99 };
|
||||
|
||||
auto end = etl::unique_copy(data.begin(), data.end(), result.begin());
|
||||
|
||||
CHECK(end == result.begin());
|
||||
CHECK_EQUAL(99, result[0]); // output unchanged
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_single_element)
|
||||
{
|
||||
std::array<int, 1> data = { 42 };
|
||||
std::array<int, 1> expected = { 42 };
|
||||
std::array<int, 1> result = {};
|
||||
|
||||
auto end = etl::unique_copy(data.begin(), data.end(), result.begin());
|
||||
|
||||
CHECK_EQUAL(1, std::distance(result.begin(), end));
|
||||
bool is_same = std::equal(expected.begin(), expected.end(), result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_no_duplicates)
|
||||
{
|
||||
std::array<int, 5> data = { 1, 2, 3, 4, 5 };
|
||||
std::array<int, 5> expected = { 1, 2, 3, 4, 5 };
|
||||
std::array<int, 5> result = {};
|
||||
|
||||
auto end = etl::unique_copy(data.begin(), data.end(), result.begin());
|
||||
|
||||
CHECK_EQUAL(5, std::distance(result.begin(), end));
|
||||
bool is_same = std::equal(expected.begin(), expected.end(), result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_all_same)
|
||||
{
|
||||
std::array<int, 5> data = { 7, 7, 7, 7, 7 };
|
||||
std::array<int, 1> expected = { 7 };
|
||||
std::array<int, 5> result = {};
|
||||
|
||||
auto end = etl::unique_copy(data.begin(), data.end(), result.begin());
|
||||
|
||||
CHECK_EQUAL(1, std::distance(result.begin(), end));
|
||||
bool is_same = std::equal(expected.begin(), expected.end(), result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_source_unchanged)
|
||||
{
|
||||
std::array<int, 10> data = { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5 };
|
||||
std::array<int, 10> original = data;
|
||||
std::array<int, 10> result = {};
|
||||
|
||||
etl::unique_copy(data.begin(), data.end(), result.begin());
|
||||
|
||||
bool is_same = std::equal(original.begin(), original.end(), data.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_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 };
|
||||
std::array<int, 10> result = {};
|
||||
|
||||
auto end = etl::unique_copy(data.begin(), data.end(), result.begin(), std::equal_to<int>());
|
||||
|
||||
CHECK_EQUAL(5, std::distance(result.begin(), end));
|
||||
bool is_same = std::equal(expected.begin(), expected.end(), result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_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 };
|
||||
std::array<int, 8> result = {};
|
||||
|
||||
auto end = etl::unique_copy(data.begin(), data.end(), result.begin(), [](int a, int b) { return (b - a) < 3; });
|
||||
|
||||
CHECK_EQUAL(3, std::distance(result.begin(), end));
|
||||
bool is_same = std::equal(expected.begin(), expected.end(), result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_matches_std)
|
||||
{
|
||||
std::array<int, 12> data = { 1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 5 };
|
||||
std::array<int, 12> std_result = {};
|
||||
std::array<int, 12> etl_result = {};
|
||||
|
||||
auto std_end = std::unique_copy(data.begin(), data.end(), std_result.begin());
|
||||
auto etl_end = etl::unique_copy(data.begin(), data.end(), etl_result.begin());
|
||||
|
||||
size_t std_size = std::distance(std_result.begin(), std_end);
|
||||
size_t etl_size = std::distance(etl_result.begin(), etl_end);
|
||||
|
||||
CHECK_EQUAL(std_size, etl_size);
|
||||
bool is_same = std::equal(std_result.begin(), std_end, etl_result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(unique_copy_with_predicate_matches_std)
|
||||
{
|
||||
std::array<int, 12> data = { 1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 5 };
|
||||
std::array<int, 12> std_result = {};
|
||||
std::array<int, 12> etl_result = {};
|
||||
|
||||
auto std_end = std::unique_copy(data.begin(), data.end(), std_result.begin(), std::equal_to<int>());
|
||||
auto etl_end = etl::unique_copy(data.begin(), data.end(), etl_result.begin(), std::equal_to<int>());
|
||||
|
||||
size_t std_size = std::distance(std_result.begin(), std_end);
|
||||
size_t etl_size = std::distance(etl_result.begin(), etl_end);
|
||||
|
||||
CHECK_EQUAL(std_size, etl_size);
|
||||
bool is_same = std::equal(std_result.begin(), std_end, etl_result.begin());
|
||||
CHECK(is_same);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
struct generator
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user