How to remove duplicates from std::vector <std::pair<UnicodeString, UnicodeString> > - c++

how to remove duplicate values from
std::vector <std::pair<UnicodeString, UnicodeString> > myVect;
Is there any built in function or i need to write a custom code for this

Assuming that (a) a std::set is not what you want [that is you want to allow duplicate elements in your std::vector, only to remove them later] and (b) you don't wish to change the order of the elements in your std::vector [that is, the current order is important], which are both reasonable situations... You should be able to adapt Fred Nurk's answer to How can I remove duplicate values from a list in C++ buy substituting vector for list and modifying the less comparators accordingly.

The best way to do it, if you can modify the order in your vector is the following:
std::sort(myVect.begin(), myVect.end());
myVect.erase(std::unique(myVect.begin(), myVect.end()), myVect.end());
Just make sure UnicodeString accepts the < operator.
However, you may want to use a different structure such as std::set or std::unordered_set to have an unique guarantee at insertion.

Related

iterating over an unordered_set

I need help iterating over an unordered map in C++. I am trying to put the elements of the set into an array so that I can sort the array.
for(auto it=s.begin();it!=s.end();it++){
a[i]=*it;
i++;
}
Your are using many differen terms here.
unordered_set
unordered_map
set
array
So, it is a little bit unclear what you really want to do.
If you have a std::unordered_setand want to put the data into a std::set, then you can simply use its range constructor and write something like std::set<int> ordered(s.begin(),s.end());
The same would work with a std::vector which has also a range constructor. Arrays, either C-style or C++ std::array are more complicated, because you need to know the size of the original data in advance. Because: Arrays have a compile time definde fixed size.
For sorting std::maps or std::unordered_maps according to their "value" and not the key, you need to use a std::multiset with a special sorting functor or lambda. If you edit your question and give more details, then I will provide source code to you.

C++ feature, like std::set, which allows duplicates

I have an std::set, which stores std::pairs of two integers. The std::set is also sorted, by allowing me to pass a helping class. However, I have written many lines of code so far and now, at the last tests, "they" told me something, that actually means that I need to allow possible duplicates in the std::set. Of course this isn't done with std::set. Any alternative that will not make me change the whole-big project?
In short, I use the std::set as an ordered list with data an std::pair of two ints.
You can use std::multiset. That should work for what you are describing.
std::multiset is the answer, as suggested by WhozCraig.

How to retrieve the elements from map in the order of insertion?

I have a map which stores <int, char *>. Now I want to retrieve the elements in the order they have been inserted. std::map returns the elements ordered by the key instead. Is it even possible?
If you are not concerned about the order based on the int (IOW you only need the order of insertion and you are not concerned with the normal key access), simply change it to a vector<pair<int, char*>>, which is by definition ordered by the insertion order (assuming you only insert at the end).
If you want to have two indices simultaneously, you need, well, Boost.MultiIndex or something similar. You'd probably need to keep a separate variable that would only count upwards (would be a steady counter), though, because you could use .size()+1 as new "insertion time key" only if you never erased anything from your map.
Now I want to retrieve the elements in the order they have been inserted. [...] Is it even possible?
No, not with std::map. std::map inserts the element pair into an already ordered tree structure (and after the insertion operation, the std::map has no way of knowing when each entry was added).
You can solve this in multiple ways:
use a std::vector<std::pair<int,char*>>. This will work, but not provide the automatic sorting that a map does.
use Boost stuff (#BartekBanachewicz suggested Boost.MultiIndex)
Use two containers and keep them synchronized: one with a sequential insert (e.g. std::vector) and one with indexing by key (e.g. std::map).
use/write a custom container yourself, so that supports both type of indexing (by key and insert order). Unless you have very specific requirements and use this a lot, you probably shouldn't need to do this.
A couple of options (other than those that Bartek suggested):
If you still want key-based access, you could use a map, along with a vector which contains all the keys, in insertion order. This gets inefficient if you want to delete elements later on, though.
You could build a linked list structure into your values: instead of the values being char*s, they're structs of a char* and the previously- and nextly-inserted keys**; a separate variable stores the head and tail of the list. You'll need to do the bookkeeping for that on your own, but it gives you efficient insertion and deletion. It's more or less what boost.multiindex will do.
** It would be nice to store map iterators instead, but this leads to circular definition problems.

A data type like vector but sorted

Is there a data type like vector or queue where you can easily add items, but when they get added, they are automatically inserted in the right order?
Also is there an easy way to delete an item from a vector or queue if you know what it is, without having to actually search through and find it?
Sounds like you want std::set or std::multi_set.
I know no such container.
std::sort exists, in which you can specifiy the sorting function, but it is often even more efficient to actually insert items in the right place directly.
If you always do that, the only "problem" you have to solve is to add an item into an already sorted list, which can be done at worst in linear time.
Note that std::vector<T>::insert() takes an iterator as a parameter, to indicate where to do the insertion. You might want to write a findPosition() methods that returns such an iterator. Then, writing an sorted_insert() method is trivial and becomes something like:
std::vector<int>::iterator findPosition(int v);
void sorted_insert(std::vector<int>& vec, int v) { vec.insert(findPosition(v), v); }
void foo()
{
std::vector<int> vec;
sorted_insert(vec, 4);
}
It sounds like you are looking for a set and not a vector. It will be sorted according to the natural ordering (the < operator). To remove an element by value call erase.
Alternately you can just use sort on a vector to sort the elements. If you need random access to the elements then you will want this approach; the sorted containers do not provide random access.
To find an element in a sorted vector you can use binary_search.
Depends on what you need and why do you need it.
No, in the standard lib, there's no "sorted" vector or queue. You have 2 options, if you want to use only the standard library:
sort the container(vector or queue) on each insertion/deletion
implement your own insert/delete, by implementing the insertion sort
Other option is to use map or set, if they'll be OK for your problem (as we don't know what it is)
The other option is to look for some 3rd party lib - I guess boost will have such container, but I don't really know that.
"Also is there an easy way to delete an item from a vector or queue if you know what it is"
- what do you mean by that? You have an iterator to it or ? Or its index? I'll edit my answer when you update (:

Which STL container to use if I want it to ignore duplicated elements?

I am looking for some STL (but not boost) container, which after the following operations will contain 2 elements: "abc" and "xyz":
std::XContainer<string> string_XContainer;
string_XContainer.push_back("abc");
string_XContainer.push_back("abc");
string_XContainer.push_back("xyz");
By the way, I need it just in order to call string_XContainer.size() in the end, to get the total number of unique strings. So maybe I don't even need a container, and there is a more elegant way of doing it?
std::set is the one you are after. A set will contain at most one instance of each element, compared according to some comparator function you define.
This would be one approach to get the number of unique strings. From your example, the strings were already in sorted order? If that's the case, then you could just create an array (or some other simple structure) and use the std::unique algorithm.