C++ || How To Get Distinct & Unique Values In An Array/Vector/Container & Remove Duplicates Using C++
The following is a module with functions which demonstrates how to get distinct and unique values in an array/vector/container and remove duplicates using C++.
The function demonstrated on this page is a template, so it should work on containers of any type.
The function also does not require a sort, it preserves the original order of the vector, uses the equality operator (operator==), and allows for a custom predicate comparison function to determine whether the arguments are equal.
1. Distinct – String Array
The example below demonstrates the use of ‘Utils::distinct‘ to get the distinct elements from an array.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Distinct - String Array // Declare array std::string names[] = { "Kenneth", "Jennifer", "Lynn", "Sole", "Kenneth", "Jennifer" }; // Get array size int size = sizeof(names) / sizeof(names[0]); // Get distinct values auto results = Utils::distinct(names, names + size); // Display results for (const auto& name : results) { std::cout << "Name: " << name << std::endl; } // expected output: /* Name: Kenneth Name: Jennifer Name: Lynn Name: Sole */ |
2. Distinct – Object Vector
The example below demonstrates the use of ‘Utils::distinct‘ to get the distinct elements from an object vector.
The object in this example overloads the equality operator to determine whether arguments are equal.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// Distinct - Object Vector // Declare object struct Person { int id; std::string name; bool operator==(const Person& rhs) const {return name == rhs.name;} }; // Declare data std::vector<Person> people = { {31, "Kenneth"}, {28, "Jennifer"}, {87, "Lynn"}, {91, "Sole"}, {22, "Kenneth"}, {19, "Jennifer"} }; // Get distinct values using object equality operator auto results = Utils::distinct(people.begin(), people.end()); // Display results for (const auto& person : results) { std::cout << "ID: " << person.id << ", Name: " << person.name << std::endl; } // expected output: /* ID: 31, Name: Kenneth ID: 28, Name: Jennifer ID: 87, Name: Lynn ID: 91, Name: Sole */ |
3. Distinct – Object Vector Predicate
The example below demonstrates the use of ‘Utils::distinct‘ to get the distinct elements from an object vector.
In this example, a predicate is used to determine whether arguments are equal.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Distinct - Object Vector Predicate // Declare object struct Person { int id; std::string name; }; // Declare data std::vector<Person> people = { {31, "Kenneth"}, {28, "Jennifer"}, {87, "Lynn"}, {91, "Sole"}, {22, "Kenneth"}, {19, "Jennifer"} }; // Declare custom comparison predicate auto pred = [](const auto& lhs, const auto& rhs) {return lhs.name == rhs.name;}; // Get distinct values using predicate auto results = Utils::distinct(people.begin(), people.end(), pred); // Display results for (const auto& person : results) { std::cout << "ID: " << person.id << ", Name: " << person.name << std::endl; } // expected output: /* ID: 31, Name: Kenneth ID: 28, Name: Jennifer ID: 87, Name: Lynn ID: 91, Name: Sole */ |
4. Utils Namespace
The following is the Utils Namespace. Include this in your project to start using!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
// ============================================================================ // Author: Kenneth Perkins // Date: Jan 22, 2021 // Taken From: http://programmingnotes.org/ // File: Utils.h // Description: Handles general utility functions // ============================================================================ #pragma once #include <vector> #include <algorithm> #include <iterator> namespace Utils { /** * FUNCTION: distinct * USE: Returns distinct elements in the given range [first, last) * @param first: The first position of the sequence * @param last: The last position of the sequence * @param predicate: A comparison function to check whether arguments are equal * @return: A container with distinct elements from the given range */ template<typename InputIt, typename T = typename std::iterator_traits<InputIt>::value_type, typename Pred> std::vector<T> distinct(InputIt first, InputIt last, const Pred& predicate) { std::vector<T> results; std::copy_if(first, last, std::back_inserter(results), [&](const T& lhs) { return std::find_if(results.begin(), results.end(), [&](const T& rhs) { return predicate(lhs, rhs); }) == results.end(); } ); return results; } /** * FUNCTION: distinct * USE: Returns distinct elements in the given range [first, last) * @param first: The first position of the sequence * @param last: The last position of the sequence * @return: A container with distinct elements from the given range */ template<typename InputIt, typename T = typename std::iterator_traits<InputIt>::value_type> std::vector<T> distinct(InputIt first, InputIt last) { auto pred = [](const T& x, const T& y) { return x == y; }; return distinct(first, last, pred); } }// http://programmingnotes.org/ |
5. More Examples
Below are more examples demonstrating the use of the ‘Utils‘ Namespace. Don’t forget to include the module when running the examples!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
// ============================================================================ // Author: Kenneth Perkins // Date: Jan 22, 2021 // Taken From: http://programmingnotes.org/ // File: program.cpp // Description: The following demonstrates the use of the Utils Namespace // ============================================================================ #include <iostream> #include <string> #include <exception> #include <vector> #include "Utils.h" void display(const std::string& message); int main() { try { // Declare array std::string names[] = { "Kenneth", "Jennifer", "Lynn", "Sole", "Kenneth", "Jennifer" }; // Get array size int size = sizeof(names) / sizeof(names[0]); // Get distinct values auto results = Utils::distinct(names, names + size); // Display results for (const auto& name : results) { display("Name: " + name); } display(""); // Declare object struct Person { int id; std::string name; bool operator==(const Person& rhs) const { return name == rhs.name; } }; // Declare data std::vector<Person> people = { {31, "Kenneth"}, {28, "Jennifer"}, {87, "Lynn"}, {91, "Sole"}, {22, "Kenneth"}, {19, "Jennifer"} }; // Get distinct values using object equality operator auto results2 = Utils::distinct(people.begin(), people.end()); // Display results for (const auto& person : results2) { display("ID: " + std::to_string(person.id) + ", Name: " + person.name); } display(""); // Declare custom comparison predicate auto pred = [](const auto& lhs, const auto& rhs) { return lhs.name == rhs.name; }; // Get distinct values using predicate auto results3 = Utils::distinct(people.begin(), people.end(), pred); // Display results for (const auto& person : results3) { display("ID: " + std::to_string(person.id) + ", Name: " + person.name); } } catch (std::exception& e) { display("\nAn error occurred: " + std::string(e.what())); } std::cin.get(); return 0; } void display(const std::string& message) { std::cout << message << std::endl; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Leave a Reply