C++ || How To Get Distinct & Unique Values In A Vector & Remove Duplicates Using C++

The following is a module with functions which demonstrates how to get distinct and unique values in a vector and remove duplicates using C++.
The function demonstrated on this page is a template, so it should work on vectors 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 Vector
The example below demonstrates the use of ‘Utils::distinct‘ to get the distinct elements from a vector.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// Distinct - String Vector // Declare names std::vector<std::string> names = { "Kenneth", "Jennifer", "Lynn", "Sole", "Kenneth", "Jennifer" }; // Get distinct values auto results = Utils::distinct(names); // Display results for (const auto& name : results) { std::cout << "Name: " + name << std::endl; } // example 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); // Display results for (const auto& person : results) { std::cout << "ID: " + std::to_string(person.id) + ", Name: " + person.name << std::endl; } // example 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, pred); // Display results for (const auto& person : results) { std::cout << "ID: " + std::to_string(person.id) + ", Name: " + person.name << std::endl; } // example 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 |
// ============================================================================ // 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 from a sequence * @param source: The container to remove duplicate elements from * @param predicate: A comparison function to check whether arguments are equal * @return: An container with distinct elements from the source sequence */ template<typename T, typename Pred> std::vector<T> distinct(const std::vector<T>& source, const Pred& predicate) { std::vector<T> results; std::copy_if(source.begin(), source.end(), 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 from a sequence * @param source: The container to remove duplicate elements from * @return: An container with distinct elements from the source sequence */ template<typename T> std::vector<T> distinct(const std::vector<T>& source) { auto pred = [](const T& x, const T& y) { return x == y; }; return distinct(source, 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 |
// ============================================================================ // 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 names std::vector<std::string> names = { "Kenneth", "Jennifer", "Lynn", "Sole", "Kenneth", "Jennifer" }; // Get distinct values auto results = Utils::distinct(names); // 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); // 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, 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