append set to another set - c++

Is there a better way of appending a set to another set than iterating through each element ?
i have :
set<string> foo ;
set<string> bar ;
.....
for (set<string>::const_iterator p = foo.begin( );p != foo.end( ); ++p)
bar.insert(*p);
Is there a more efficient way to do this ?

You can insert a range:
bar.insert(foo.begin(), foo.end());

It is not a more efficient but less code.
bar.insert(foo.begin(), foo.end());
Or take the union which deals efficiently with duplicates. (if applicable)
set<string> baz ;
set_union(foo.begin(), foo.end(),
bar.begin(), bar.end(),
inserter(baz, baz.begin()));

Related

How to iterate over an unordered map's specific key's values?

I have an unordered map with a string and a vector of strings. I want to go to a specific key and iterate over all it's values.
Ex. Go to key 400 and iterate over 1, 2, and 3.
{
400 -> [1,2,3],
200 -> [],
13 -> [10,30]
}
std::unordered_map<std::string, std::vector<std::string>> mymap;
myKey = 400;
for(auto elem: mymap){
if(elem.first == myKey){
for(auto elem2: elem.first.size()){
//do stuff here
}
}
}
You don't need 2 loops to do this. Specifically, the outer loop that looks for the key is unnecessary. If you know that the key exists, you could simply do:
for (auto const & item : mymap["400"])
// ...
If you're not sure whether the key exists, you can write:
if (auto it = mymap.find("400");
it != mymap.end())
for (auto const & item : it->second)
// ...
Or from C++20, just:
if (mymap.contains("400"))
for (auto const & item : mymap["400"])
// ...

Find index of element in vector of pairs

As stated in the title, I'm trying to find the index of an element in a vector of pairs. I have the following vector: std::vector<std::pair<std::string, double>> dict.
The content of my dict is:
Name1 11
Name2 9
Name3 10
Name4 12
Name5 13
All I have in order to find the index is the first attribute of the pair. For example I have Name5 and I would like to find 4. (Since Name5 is the fifth element).
Does anyone have an idea how to do it ?
I tried something but it doesn't seem to work:
auto it = std::find(dict.begin(), dict.end(), movieName);
where movieName is an std::string with "Name5" inside.
Thank you!
You can use a predicate to decide which entries in the vector should match. It's easiest to do that with a lambda:
auto it = std::find_if(dict.begin(), dict.end(),
[&](const auto& pair) { return pair.first == movieName; });
After you have the iterator, compare it to dict.end() to see if there was any match, and if there's a match you can convert it to an index into the vector using std::distance(), as d4rk4ng31 commented under the question.
I would simply go with a normal for_each loop.
So:
int index = 0;
for(const auto& pair : dict) {
if(pair.first == <whatever>) {
break;
}
index++;
}
//if index == dict.size() then print element not found
Other way would be using std::find_if() ( Thanks #Tony Delroy :) )
auto index = std::distance(dict.begin(), std::find_if(dict.begin(), dict.end(), [&](const auto& pair) { return pair.first == movieName; }));

How to compare pairs by other field only in c++?

Im having this issue with comparing pairs. I want use find() to my vector which contains pairs like this:
vector<pair<PersonID, Cost>> friendlist;
PersonID and Cost are both just regular ints. And the problem here is that I want to specifically use the find() just on the PersonID, I'm not interested on the Cost.
if(friendlist.begin(), friendlist.end(), std::make_pair(toid, Cost)) !=
friendlist.end() )
toid here is the id I want to look for within the vector. So what I should do with the other field that make_pair requires?
std::find_if(friendlist.begin(), friendlist.end(),
[=](const std::pair<PersonID, Cost>& elem) {
return elem.first == toid;
});

Delete list element from class

I try to delete list element and always get error message.
Firstly I have this class structure :
Class X
{ public:
ID;
name;
}
then I have list container.
Now, I want to delete specific element from container.
void delete ( list<X> a , X b )
{
list<X>::iterator itr;
for ( itr =a.begin() ; itr != a.end() ; itr++ )
{
if ( *itr.ID == b.ID )
{ a.erase(itr) ; }
}
}
But, I get error:
" iterator doesn't have ID ".
How can I fix it?
This is because the dot operator . is "stronger" than the dereference operator *. According to this table, dot has a precedence of two, while dereference asterisk * has a precedence of three (lower is stronger). This means that without the parentheses the compiler tries to get iterator's member ID, and then dereference the value of ID. This is not possible, because the iterator has no member called ID.
You need to put parentheses to enforce the precedence that you want:
if ( (*itr).ID == b.ID )
Alternatively, you can use the -> operator to dereference the iterator:
if ( itr->ID == b.ID )
Note: C++ Standard Library provides a way to do this without a loop:
a.erase(
remove_if(
a.begin()
, a.end()
, [](X x){ return x.ID == b.ID; }
)
, a.end()
);
Demo on ideone.
i prefer to use itr->ID instead of *itr.ID. the later is a little confusing sometime.

In C++ using NaCl how to sort a JSON object by value?

I'm using PicoJSON to handle JSON that I get from JavaScript into C++.
If I have a JSON with keys and values of the form {"val1":3, "val2":4} I can get the value of every specific key like so:
picojson::value v;
const string json2("{\"val1\":3,\"val2\":4}");
int val1 = (int)v.get("val1").get<double>(); // val1 will be equal to 3
int val2 = (int)v.get("val2").get<double>(); // val2 will be equal to 4
The problem is that I have an array of objects coming from JavaScript in the form of JSON that look like [{"name": 3},{"name": 1},{"name": 2}]. So now the code will look like this:
picojson::value v;
const string json1("[{\"name\": 3},{\"name\": 1},{\"name\": 2}]");
I am expected to sort them so the expected output should be:
"[{\"name\": 1},{\"name\": 2},{\"name\": 3}]"
Do I have to use a 'for loop' with a linked list to somehow extract that data to sort it? If so, how?
Maybe this can be extracted using regular expressions? If so, how?
Should the array can be converted into array of arrays in order to sort it? If so, how?
Do I have to build a struct or a vector to get a sortable data structure recognisable by
C++? If so, how?
Note: The number of elements varies - it can be greater/smaller.
EDIT:
Can this task be solved if the data structure is in this form (just like I had with {"val1":3, "val2":4} ) :
{"name3": 3, "name1" : 1, "name2": 2, "name97" : 97, ... }
I am flexible to changing it so that C++ would be able to handle it.
Would it then be possible to traverse every key and sort in by value ? If yes, how to do it?
You can put your data into a vector and sort it.
array arr = v.get<array>();
vector<int> vi;
for (array::const_iterator it = arr.begin(); it != arr.end(); ++it) {
vi.push_back((int)(*it).get("name").get<double>());
}
sort(vi.begin(), vi.end());
stringstream ss;
vector<int>::const_iterator it;
for (ss<<"[", it = vi.begin(); (it+1) != vi.end(); ++it) {
ss<<"{\"name\": "<<(*it)<<"},";
}
ss<<"{\"name\": "<<(*it)<<"}]";
cout<<"Output: "<<ss.str()<<endl;
Here is outputs:
Input: [{"name": 3},{"name": 1},{"name": 2}]
Output: [{"name": 1},{"name": 2},{"name": 3}]