finding elements of set in a map - c++

I have two maps, tk1 and tk2 with the following structure:
std::map<std::string, double>tk1;
std::map<std::string, double>tk2;
tk1 contains the following data:
2011-01-03 2200
2011-01-04 2209
2011-01-05 2300
and tk2 contains the following data:
2011-01-03 2450
2011-01-04 2465
2011-01-06 2476
2011-01-07 2457
I have created a set that contains the dates as strings as in
std::set<std::string>dateset;
std::set<std::string>new_dateset;
I created it by iterating through the 2 maps and inserting into the set as in
dateset.insert(it->first);
dateset has the following values:
2011-01-03
2011-01-04
2011-01-05
2011-01-06
2011-01-07
I want to populate new_dateset so it only contains the dates that are in both tk1 and tk2, i.e. new_dateset should contain only
2011-01-03
2011-01-04
I wrote the following:
std::set<std::string>::iterator it1=dateset.begin(), end1=dateset.end();
std::map<std::string, double>::iterator it2=tk1.begin(), end2=tk1.end();
std::map<std::string, double>::iterator it3=tk2.begin(), end3=tk2.end();
while (it1 != end1) {
if (it2->first == *it1)
new_dateset.insert(it2->first);
++it1;
}
but obviously I am not doing it correctly. Can someone suggest the best way to do this.

You might consider std::set_intersection with the key_iterator from a previous answer.

Iterate over it1, check if first for each element is in tk2 using the find() method, and insert it into the set if it is there. What you are doing in your example is to check elements in dataset, which contain keys that are in tk1 OR tk2.
for(; it2 != end2; ++it2) {
if(tk2.find(it2->first) != end3) new_dataset.insert(it2->first);
}

You should compare strings as follows:
if(it2->first.compare(*it) == 0)
{
//strings match, do something.
}
else
{
// no match do something else.
}

Iterate over elements in tk1 and see if the keys exist in tk2. If it does, then insert.
for(; it2 != end2; ++it2)
{
if(tk2.find(it2->first) != end3)
{
new_dataset.insert(it2->first);
}
}

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;
});

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}]

append set to another set

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()));