Converting a vector to a set in C++ is helpful when you want to get rid of duplicate elements in a group of items. Vectors are arrays that can have many elements of the same type, while sets are containers that only hold unique elements in a particular sequence.
To convert a vector to a set, you copy all the vector elements into the set, so that only the distinct ones remain. You can then use the set for operations that need only unique elements.
However, the set’s element order may differ from that of the original vector since sets have a different order.
Why is there a need to convert vector to set in C++?
Reasons to convert a vector to a set in C++:
Remove duplicates: Converting a vector to a set removes duplicates and provides a container with only unique elements.
Faster search: Sets use a balanced binary tree that enables efficient searching and insertion, making searching faster than in vectors, especially for large collections.
Maintain order: Sets maintain a specific order of elements, helpful when you need to keep a specific order based on the comparison operator.
Set operations: Sets offer built-in set operations, like union, intersection, and difference that you can use on the elements once you convert a vector to a set.
Better memory usage: Sets have a smaller memory footprint than vectors because they only store unique elements. Vectors can store multiple copies of the same element, making sets more efficient for large collections.
Methods for converting vector to set in C++:
Following are the several ways to convert vector to set in C++:
- Using the constructor of std::set.
- Using the std::copy algorithm in conjunction with std::inserter.
- Using the std::unique and std::sort algorithms.
- Using a loop.
- Using std::transform and std::set.
A thorough explanation of each strategy:
1. Using the constructor of std::set:
This is the simplest and most straightforward way to convert a vector to a set. You can create a set and pass the two iterators representing the beginning and end of the vector as parameters to the constructor of the set. The set will be created with the elements of the vector, without any duplicates.
Program-
#include <iostream>
#include <vector>
#include <set>
int main() {
std::vector<int> vec = {1, 2, 3, 1, 2, 3};
// Create a set from the vector using the constructor
std::set<int> myset(vec.begin(), vec.end());
// Print the elements of the set
for (const auto& element : myset) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
Output-
1 2 3
Explanation:
- We create a vector vec with some elements, including duplicates.
- We create a set myset using the constructor of std::set, passing the iterators representing the beginning and end of the vector as parameters.
- The set myset is automatically created with the elements of the vector, but with duplicates removed.
- Finally, we print the elements of the set using a range-based for loop.
2. Using the std::copy algorithm in conjunction with std::inserter:
This method involves using the std::copy algorithm to copy the elements of the vector to a set. You can use the std::inserter function to insert the elements into the set. This method is useful if you want to add elements to an existing set or if you need to customize the behavior of the inserter.
Program-
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 1, 2, 3};
std::set<int> myset;
// Copy the elements of the vector to the set using std::copy and std::inserter
std::copy(vec.begin(), vec.end(), std::inserter(myset, myset.begin()));
// Print the elements of the set
for (const auto& element : myset) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
Output-
1 2 3
Explanation:
- A vector vec with duplicates is created.
- An empty set myset is created.
- The elements of vec are copied to myset using std::copy and an std::inserter object.
- The beginning iterator of myset is used to specify where the copied elements should be inserted.
- The elements of myset are printed using a range-based for loop.
3. Using the std::unique and std::sort algorithms:
This method involves sorting the vector using the std::sort algorithm and then removing the duplicates using the std::unique algorithm. Finally, a set is created from the sorted and unique vector. This method is useful if you need to ensure that the set contains only unique elements.
Program-
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 1, 2, 3};
std::set<int> myset;
// Sort the vector and remove duplicates using std::unique
std::sort(vec.begin(), vec.end());
auto last = std::unique(vec.begin(), vec.end());
// Copy the unique elements of the vector to the set
std::copy(vec.begin(), last, std::inserter(myset, myset.begin()));
// Print the elements of the set
for (const auto& element : myset) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
Output-
1 2 3
Explanation:
- We create a vector with some elements, including duplicates, and an empty set.
- The vector is sorted using std::sort and duplicates are removed using std::unique.
- The unique elements of the vector are copied to the set using std::copy and an std::inserter object.
- The elements of the set are printed using a range-based for loop.
4. Using a loop:
This method involves iterating over the elements of the vector and inserting them one by one into the set. This method is useful if you need to perform additional processing on each element of the vector before inserting it into the set.
Program-
#include <iostream>
#include <vector>
#include <set>
int main() {
std::vector<int> vec = {1, 2, 3, 1, 2, 3};
std::set<int> myset;
// Loop through the elements of the vector and insert them into the set
for (const auto& element : vec) {
myset.insert(element);
}
// Print the elements of the set
for (const auto& element : myset) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
Output-
1 2 3
Explanation:
- We create a vector vec with some elements, including duplicates.
- We create an empty set myset.
- We loop through the elements of the vector vec using a range-based for loop, and insert each element into the set myset using the std::set::insert method.
- Finally, we print the elements of the set using a range-based for loop.
5. Using std::transform and std::set:
This method involves using the std::transform algorithm to apply a transformation to each element of the vector, and then inserting the transformed elements into a set. This method is useful if you need to perform a transformation on the elements of the vector before inserting them into the set.
Program-
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 1, 2, 3};
std::set<int> myset;
// Copy the unique elements of the vector to the set using std::transform
std::transform(vec.begin(), vec.end(), std::inserter(myset, myset.begin()),
[](const auto& element) { return element; });
// Print the elements of the set
for (const auto& element : myset) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
Output-
1 2 3
Explanation:
- We create a vector vec with some elements, including duplicates.
- We create an empty set myset.
- We use the std::transform algorithm to copy the unique elements of the vector vec to the set myset, using a lambda function that returns the element itself. The std::inserter object acts as an output iterator for the set, inserting the copied elements at the beginning of the set.
- Finally, we print the elements of the set using a range-based for loop.
Best approach for converting vector to set in C++:
The constructor of std::set is the best approach to convert a vector to a set for several reasons:
- Efficient: no additional loops or algorithms, faster for large data sets
- Automatic duplicate removal: saves time and effort, no need for extra code
- Readable: easy to follow and maintain
- Concise: requires only one line of code, reduces risk of errors
Sample Problems:
Problem 1:
Write a C++ program for an e-commerce app to remove duplicate items in a vector by converting it to a set using std::set constructor. Alert the user and remove duplicates if found, else print a message indicating no duplicates found.
Program-
#include <iostream>
#include <vector>
#include <set>
int main() {
// Create a vector of items in the cart
std::vector<std::string> cart = {"Shirt", "Pants", "Shoes", "Shirt", "Hat"};
// Convert the vector to a set using the constructor of std::set
std::set<std::string> cart_set(cart.begin(), cart.end());
// Check if the size of the set is not the same as the size of the vector
if (cart_set.size() != cart.size()) {
// Print a message indicating duplicates were found
std::cout << "Duplicates found in cart. Removing duplicates...\n";
// Remove duplicates from the vector
cart.assign(cart_set.begin(), cart_set.end());
} else {
// Print a message indicating no duplicates were found
std::cout << "No duplicates found in cart.\n";
}
// Print the updated cart
std::cout << "Updated cart:\n";
for (const auto& item : cart) {
std::cout << "- " << item << "\n";
}
return 0;
}
Output-
Duplicates found in cart. Removing duplicates...
Updated cart:
- Hat
- Pants
- Shirt
- Shoes
Explanation-
- A vector of items in the cart is created with some duplicates.
- The vector is converted to a set to remove duplicates.
- The program checks if the size of the set is different from the size of the vector to determine if duplicates were removed.
- A message is printed to the user if duplicates were found and removed.
- If no duplicates are found, a message is printed.
- The updated cart with duplicates removed is printed.
Problem 2:
Write a C++ program for a mailing list app that removes duplicate email addresses by converting a vector to a set using std::copy and std::inserter. If duplicates are found, print a message to the user indicating that they have been removed. Otherwise, print a message indicating that the list is already unique.
Program-
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
int main() {
std::vector<std::string> emails = {"[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"};
// Convert vector to set using std::copy and std::inserter
std::set<std::string> uniqueEmails;
std::copy(emails.begin(), emails.end(), std::inserter(uniqueEmails, uniqueEmails.end()));
// Check if duplicates were removed
if (uniqueEmails.size() < emails.size()) {
std::cout << "Duplicates found and removed.\n";
emails.assign(uniqueEmails.begin(), uniqueEmails.end()); // Replace original vector with unique set
}
else {
std::cout << "List is already unique.\n";
}
// Print updated list
std::cout << "Updated mailing list:\n";
for (const auto& email : emails) {
std::cout << email << "\n";
}
return 0;
}
Output-
Duplicates found and removed.
Updated mailing list:
[email protected]
[email protected]
[email protected]
[email protected]
Explanation-
- A vector of email addresses with some duplicates is defined.
- An empty set of strings is created to store unique email addresses.
- The std::copy algorithm is used to copy elements from the vector to the set, removing duplicates in the process.
- The program checks if duplicates were removed and updates the vector accordingly.
- The program prints a message indicating whether duplicates were found and removed or not.
- The updated vector is printed.
Problem 3:
Given a vector of integers representing transaction IDs, remove the duplicates while preserving the order of the transactions using std::unique and std::sort algorithms in C++.
Program-
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// create a vector of transaction IDs with some duplicates
std::vector<int> transactions = { 1, 2, 3, 4, 2, 5, 1, 6, 7, 4 };
// sort the vector to group duplicates together
std::sort(transactions.begin(), transactions.end());
// use std::unique to remove the duplicates
auto last = std::unique(transactions.begin(), transactions.end());
// erase the duplicates from the vector
transactions.erase(last, transactions.end());
// print the unique transaction IDs
std::cout << "Unique transaction IDs:" << std::endl;
for (int id : transactions) {
std::cout << id << std::endl;
}
return 0;
}
Output-
Unique transaction IDs:
1
2
3
4
5
6
7
Explanation-
- Define a function that compares Message objects based on their timestamp and content.
- Create a vector of Message objects that may contain duplicates.
- Sort the vector using the comparison function from step 1.
- Use std::unique algorithm with a lambda function to remove consecutive duplicates in the vector.
- Erase the duplicates from the vector using the returned iterator.
- Count the number of duplicates removed.
- Print a message indicating whether duplicates were removed or not.
- Print the remaining messages in the vector after removing duplicates.
Problem 4:
Write a C++ program for a movie recommendation system that removes duplicate movies by converting a vector to a set using loop approach. Alert the user and remove duplicates if found, else print a message indicating no duplicates found.
Program-
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
int main() {
std::vector<std::string> movieList = {"The Shawshank Redemption", "The Godfather", "The Dark Knight", "The Godfather", "The Dark Knight Rises", "The Shawshank Redemption"};
std::vector<std::string> uniqueMovies;
std::set<std::string> uniqueMovieSet;
bool foundDuplicates = false;
// converting vector to set using loop approach
for (const auto& movie : movieList) {
auto res = uniqueMovieSet.insert(movie);
if (res.second) {
uniqueMovies.push_back(movie);
} else {
foundDuplicates = true;
}
}
if (foundDuplicates) {
std::cout << "Duplicates found in your list. Removed duplicates.\n";
} else {
std::cout << "No duplicates found in your list.\n";
}
std::cout << "Movie List:\n";
for (const auto& movie : uniqueMovies) {
std::cout << movie << "\n";
}
return 0;
}
Output-
Duplicates found in your list. Removed duplicates.
Movie List:
The Shawshank Redemption
The Godfather
The Dark Knight
The Dark Knight Rises
Explanation-
- The code creates a vector named “movieList” with movie titles.
- It creates an empty vector “uniqueMovies” to store unique movies and a set “uniqueMovieSet” to store unique movies as well.
- A boolean variable “foundDuplicates” is created and initialized as false.
- A for loop is used to iterate through “movieList”, insert each movie into “uniqueMovieSet”, and check whether the insertion was successful.
- If insertion was successful, the movie is pushed to “uniqueMovies”. If not, “foundDuplicates” is set to true.
- A message is displayed indicating whether duplicates were found or not.
- “uniqueMovies” is printed to the console.
Problem 5:
Given a vector of strings containing names of students and their corresponding grades, find the unique grades in the vector using std::transform and std::set approach and calculate the average grade for each unique grade.
Program-
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <iomanip>
int main() {
std::vector<std::pair<std::string, int>> studentGrades = {
{"John", 80},
{"Sarah", 90},
{"Mike", 70},
{"John", 85},
{"Sarah", 95},
{"Mike", 75},
{"John", 90},
{"Sarah", 90},
{"Mike", 80}
};
// extract the grades into a separate vector using std::transform
std::vector<int> grades(studentGrades.size());
std::transform(studentGrades.begin(), studentGrades.end(), grades.begin(),
[](const std::pair<std::string, int>& pair) {
return pair.second;
}
);
// use a std::set to get the unique grades
std::set<int> uniqueGrades(grades.begin(), grades.end());
// calculate the average grade for each unique grade using a std::map
std::map<int, double> avgGrades;
for (const auto& grade : uniqueGrades) {
// use std::accumulate to get the sum of grades for this grade value
double sum = std::accumulate(studentGrades.begin(), studentGrades.end(), 0.0,
[grade](double sum, const std::pair<std::string, int>& pair) {
return sum + (pair.second == grade ? pair.second : 0);
}
);
// calculate the average grade for this grade value
double avg = sum / std::count_if(studentGrades.begin(), studentGrades.end(),
[grade](const std::pair<std::string, int>& pair) {
return pair.second == grade;
}
);
avgGrades[grade] = avg;
}
// print the unique grades and their average grades
std::cout << "Unique grades and their average grades:\n";
std::cout << std::fixed << std::setprecision(2);
for (const auto& pair : avgGrades) {
std::cout << pair.first << ": " << pair.second << "\n";
}
return 0;
}
Output-
Unique grades and their average grades:
70: 70.00
75: 75.00
80: 80.00
85: 85.00
90: 91.67
95: 95.00
Explanation-
- We have a vector of pairs, where each pair contains a student’s name and their grade.
- We extract the grades from the pairs into a separate vector using std::transform.
- We use a std::set to get the unique grades in the vector.
- We loop through each unique grade, and use std::accumulate to calculate the sum of grades for that grade, and std::count_if to count the number of grades for that grade. We use these values to calculate the average grade for that grade, and store it in a std::map.
- We print the unique grades and their corresponding average grades.
Conclusion:
Converting between a vector and a set is a common programming task that can be accomplished using different approaches. Understanding these concepts and implementing them in your code can help you manage data more efficiently, remove duplicates, and obtain reliable results. By choosing the appropriate approach for your specific needs, you can optimize your code’s performance and achieve the desired outcomes.