I have a map like this:
map<string, map<int, int>> collector;
And I have no idea how to insert data in my map. If I had
map<string, int> collector;
with only key-value I would use
collector.insert(pair<string, int>)(name,money));
But what is the way of inserting when we have map in map. I tried to do:
typedef map<int, int> map_;
for(iteration = collector.begin(); iteration != collector.end(); iteration++) {
iteration = collector.find(word);
if(iteration == collector.end()) {
iteration = collector.insert(map_::value_type(num,num).first;
}
}
This way is not working for me.
Here are some ways to insert into your data structure:
#include <iostream> // cout
#include <map>
#include <string>
#include <utility> // make_pair
using namespace std;
int main()
{
using Collector = map<string, map<int, int>>;
Collector collector;
collector["USD"] = Collector::mapped_type{ { 1, 3 }, { 0, 8 } };
collector["EUR"].insert(make_pair(4, 5));
collector["EUR"].insert(make_pair(6, 7));
collector["CHF"][2] = 4;
const Collector::mapped_type jpyIntegers { { 10, 20 }, { 100, 200 } };
collector.insert(make_pair("JPY", jpyIntegers));
collector["MMK"];
for (const auto& a: collector) {
cout << a.first << ": ";
for (const auto& i: a.second) {
cout << "(" << i.first << "|" << i.second << ")";
}
cout << "\n";
}
}
Related
This is my code -
Problem: The sorting comparator function which I have written is not doing anything. the code gets executed, comparator function also runs, but it does not modify my vector. And I don't understand why.
Logic(which I have written):
I have used region index as an index of my vector. For each region I have maintained a vector of (points, surname).
Then, for each region, I have sorted my vector according to their points.
then, I checked if there is no reputation in points on first position and second position, vis-a-vis for second and third position, that means we have clear winner, record them.
Print the recorded winners.
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int main() {
int participants, regions;
cin >> participants >> regions;
vector<vector<pair<int, string>>> cands(regions);
string surname;
int region, points;
for (int i{0}; i<participants; i++) {
cin >> surname >> region >> points;
cands[region-1].push_back({points, surname});
}
for (auto vec : cands) {
sort(vec.rbegin(), vec.rend(), [](pair<int, string>& x, pair<int, string>& y) {
return x.first > y.first;
});
}
// for (auto vec : cands) {
// for (auto ele : vec) cout << ele.first << " " << ele.second << endl;
// cout << endl;
// }
vector<pair<string, string>> teams;
for (auto vec : cands) {
if (vec[0].first == vec[1].first) teams.push_back({"?", ""});
else {
if (vec.size() > 2) {
if (vec[1].first == vec[2].first) teams.push_back({"?", ""});
else teams.push_back({vec[0].second, vec[1].second});
} else teams.push_back({vec[0].second, vec[1].second});
}
}
for (auto ele : teams) cout << ele.first << " " << ele.second << endl;
return 0;
}
for (auto vec : cands) {
This create a copy of the elements in cands, not the actual element of cands itself.
Change your code to:
for (auto &vec : cands) {
I have the program that has two vectors of names and ages. It sorts the names vector and keeps the age vector in the correct order to match the sorted name vector. Now, I want to make a function from existing code, but I have some issues.
Existing code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
int main() {
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
const vector<string> namesCopy = names;
sort(begin(names), end(names));
decltype(ages) sortedAges(ages.size());
for(int i = 0; i < namesCopy.size(); ++i) {
const auto iter = lower_bound(begin(names), end(names), namesCopy[i]);
const auto pos = iter - begin(names);
sortedAges[pos] = ages[i];
}
for(int i = 0 ; i < names.size() ; ++i)
cout << setw(10) << names[i] << setw(4) << sortedAges[i] << '\n' ;
}
Output
Function:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
int test(vector<string> testNames, vector<string> testNamesCopy, vector<unsigned int> testAges, vector<unsigned int> testSortedAges) {
for(int i = 0; i < testNamesCopy.size(); ++i) {
const auto iter = lower_bound(begin(testNames), end(testNames), testNamesCopy[i]);
const auto pos = iter - begin(testNames);
return testSortedAges[pos] = testAges[i];
}
}
int main() {
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
const auto namesCopy = names;
sort(begin(names), end(names));
decltype(ages) sortedAges(ages.size());
for(int i = 0 ; i < names.size() ; ++i)
cout << setw(10) << names[i] << setw(4) << test(names, namesCopy, ages, sortedAges) << '\n' ;
}
Output 2
I think you are approaching this the wrong way. Having 2 vector that you sort but have to keep in the same order is error prone. Instead you should use a vector of pair.
std::vector<std::pair<std::string, int>> idendityVec;
Then you can sort by the name (the first element of the pair) by doing
std::sort(idendityVec.begin(), idendityVec.end());
If you want to sort by age, you can declare your own comparaison function and use it in the sort :
bool lesserAge(const pair<std::string,int> &a,
const pair<std::string,int> &b)
{
return (a.second < b.second);
}
std::sort(idendityVec.begin(), idendityVec.end(), lesserAge);
Which gives you something like this :
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
bool lesserAge(const std::pair<std::string, int> &a,
const std::pair<std::string, int> &b)
{
return (a.second < b.second);
}
int main()
{
std::vector<std::pair<std::string, int>> idendityVec = {std::make_pair("three", 3), std::make_pair("four", 4), std::make_pair("two", 2), std::make_pair("one", 1)};
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
// Sort by age i.e. second element
std::sort(idendityVec.begin(), idendityVec.end(), lesserAge);
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
//Sort by name i.e first element
std::sort(idendityVec.begin(), idendityVec.end());
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
}
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
names and ages seem connected in such a way that it'd be best to group them together in a class. We can use a simple struct which, by default, gives you direct access to its members, just like you have access to all the names and ages in your current solution. You can start with this:
struct person { // ... or animal, or thing. Give it a meaningful name.
std::string name{};
unsigned age{};
};
Now you can create a std::vector<person> instead of having two unconnected vectors, which makes sorting and general handling of the data a bit of a hassle.
With the above, sorting and printing etc. becomes more straight forward. I've used lambdas to create the sorting functions in the example:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <tuple> // std::tie
#include <iomanip>
struct person {
std::string name{};
unsigned age{};
};
// print one "person"
std::ostream& operator<<(std::ostream& os, const person& p) {
return os << std::setw(10) << p.name << std::setw(4) << p.age;
}
int main() {
// one vector with all the persons
std::vector<person> persons{
{"One", 1},
{"Two", 2},
{"Three", 3},
{"Four", 4},
{"Five", 5}
};
// sort on name first, age second (if names are equal) - ascending order
std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
return std::tie(a.name, a.age) < std::tie(b.name, b.age);
});
// print the current order:
for(const auto& p : persons) std::cout << p << "\n";
std::cout << "--\n";
// sort on age first, name second (if ages are equal) - ascending order
std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
return std::tie(a.age, a.name) < std::tie(b.age, b.name);
});
// print the current order:
for(const auto& p : persons) std::cout << p << "\n";
}
Can someone please give an actual example of function that returns map in c++.
I tried answers from other posts but I don't know how to apply in my case.
This is my working code:
auto DataArray = jvalue.at(U("data")).as_array();
//Make an associative array or map with key value pair from extracted json data
std::map<int, std::string> staffMap;
// loop through 'data' object
for (int i = 0; i < DataArray.size(); i++)
{
try
{
auto data = DataArray[i];
auto dataObj = data.as_object();
int key;
std::string value;
// loop through each object of 'data'
for (auto iterInner = dataObj.cbegin(); iterInner != dataObj.cend(); ++iterInner)
{
auto &propertyName = iterInner->first;
auto &propertyValue = iterInner->second;
//std::wcout << "Property: " << propertyName << ", Value: " << propertyValue << std::endl;
if (propertyName == L"_id")
{
key = propertyValue.as_integer();
}
else if (propertyName == L"name")
{
value = conversions::to_utf8string(propertyValue.as_string());
}
}
staffMap.insert(std::make_pair(key, value));
}
catch (const std::exception& e)
{
std::wcout << e.what() << std::endl;
}
}
// Iterate through map and display in terminal
std::map<int, std::string>::iterator iter;
std::wcout << "The list of staffs" << std::endl;
for (iter = staffMap.begin(); iter != staffMap.end(); iter++)
std::cout << iter->first << " " << iter->second << " ,";
Let say I want a function:
std::map<int, std::string> staffMap;
std::map<> GetStaffMap()
{
return staffMap;
}
// Give staffMap a data here
I can't find enough tutorial for making a function that returns std::map in c++. Hope someone could help me here. Thank you.
I can't find enough tutorial for making a function that returns std::map in c++. Hope someone could help me here
You need to specify the exact type, std::map<int, std::string>:
std::map<int, std::string> GetStaffMap()
{
return staffMap;
}
If you are able to use C++14, use auto as an alternative:
auto GetStaffMap()
{
return staffMap;
}
The example below shows how to create a function in C++ that returns a map.
// Example program with a function returning a map
#include <iostream>
#include <string>
#include <map>
std::map<std::string, int>
function()
{
std::map<std::string, int> out;
out["one"] = 1;
out["two"] = 2;
return out;
}
int main()
{
std::map<std::string, int> out = function();
for (const auto & iter : out)
std::cout << iter.first << " = " << iter.second << std::endl;
}
I have a string like "aabcdba" now I want to store the position of different character's position. I am trying to store using vector and unordered_map. Is there any good approach to store the position of different characters?
void topKFrequent(string s) {
vector<vector<int> >v(123);
//unordered_map<char, vector<int>>m;
for(int i=0;i<s.size();i++) {
v[s[i]].push_back(i);
// m[s[i]].push_back(i);
}
for(int i=0;i<123;i++) {
for(int j=0;j<v[i].size();j++) {
char ch=i;
cout<<ch<<"->"<<v[i][j]<<endl;
}
}
}
if string = "aabcdba", I want the following result:
a->0,1,6;
b->2,5;
c->3;
d->4;
You could use a map<char, vector<unsigned int> >.
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
map<char, vector<unsigned int> > storePos(string s)
{
map<char, vector<unsigned int> > charPos;
for(int i=0;i<s.size();i++)
{
auto itr = charPos.find(s[i]);
if(itr != charPos.end())
{
itr->second.push_back(i);
}
else
{
charPos[s[i]] = vector<unsigned int>(1, i);
}
}
return charPos;
}
int main(void)
{
string example = "aabcdba";
auto result = storePos(example);
for(auto itr1 = result.begin(); itr1 != result.end(); itr1 ++)
{
cout << "Letter: " << itr1->first << ", Locations: ";
for(auto itr2 = itr1->second.begin(); itr2 != itr1->second.end();
itr2 ++)
{
cout << *itr2 << " ";
}
cout << endl;
}
}
If you really want to store ordinal positions in the original string sequence, you can do so with either an unordered or ordered map of char to vector, where char is the key, and the vector contains the positions. Using an unordered map will not give you the lexicographical ordering of keys you seem to be seeking, but will nonetheless give you accurate positional vectors.
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
int main()
{
std::string s = "aabcdba";
std::unordered_map<char, std::vector<unsigned int>> mymap;
for (unsigned i=0; i<s.size(); ++i)
mymap[s[i]].push_back(i);
for (auto const& pr : mymap)
{
std::cout << pr.first << "->";
auto it = pr.second.cbegin();
std::cout << *it;
while (++it != pr.second.cend())
std::cout << ',' << *it;
std::cout << ";\n";
}
}
Output
d->4;
c->3;
b->2,5;
a->0,1,6;
If you want lexicographical ordering, the simplest alternative is to simply using a regular ordered map instead. Changing only this:
std::unordered_map<char, std::vector<unsigned int>> mymap;
to this:
std::map<char, std::vector<unsigned int>> mymap;
and including the appropriate header delivers us this for output:
a->0,1,6;
b->2,5;
c->3;
d->4;
which fits exactly what you seem to be looking for.
A possible implementation to store the positions could be using unordered_multimap: (where the key characters can be repeated).
void storePos(string s) {
unordered_multimap<char, int>m;
for(int i=0;i<s.size();i++) {
m.insert(make_pair(s[i],i));
}
}
[EDITED]
But the output may depend on how you use it, or print out the data.
For example, consider the use of a std::multimap instead of std::unordered_map, to populate it you just do:
multimap<char, int>m;
void storePos(string s) {
for(int i=0;i<s.size();i++) {
m.insert(make_pair(s[i],i));
}
}
And to print the data you could have the following method:
void printPos()
{
std::multimap<char,int>::iterator it,itup;
for (it = m.begin(); it != m.end(); )
{
cout << (*it).first << " -> ";
itup = m.upper_bound ((*it).first );
// print range [it,itup):
for (it; it!=itup; ++it)
{
cout << (*it).second << ", ";
}
cout << endl;
}
}
Output:
a -> 0, 1, 6,
b -> 2, 5,
c -> 3,
d -> 4,
Try this!
So I'm having a Red Black Tree containing pairs of int, and when i call .find(x) function it will search for x (both first and second), but i want to make it ignore the second value, and look only for the first value. How can i do that?
In general, it is not possible. But for your limited case of pair of ints you can fake it using upper_bound() and std::numeric_limits<int>::min():
#include <iostream>
#include <iomanip>
#include <limits>
#include <set>
int main()
{
using key_type = std::pair<int, int>;
std::set<key_type> s { {1, -1}, {1, 3}, {2, 10}, {3, 42} };
auto it = s.upper_bound (key_type (2, std::numeric_limits<int>::min ()));
std::cout << "(" << it->first << "; " << it->second << ")\n";
}
Live on Coliru
auto fn = [](const pair<int, int>&a, const pair <int, int>&b) {
return a.first < b.first;
};
set<pair<int, int>, decltype(fn)> my_set(fn);
my_set is now a set that uses only pair.first as the key
Example:
#include <iostream>
#include <string>
#include <set>
using namespace std;
int main()
{
auto fn = [](const pair<int, int>&a, const pair <int, int>&b) {
return a.first < b.first;
};
set<pair<int, int>, decltype(fn)> my_set(fn);
my_set.insert({1, 123});
my_set.insert({4, 456});
my_set.insert({7, 789});
auto iter = my_set.find({4, 0});
if (iter != my_set.end()) {
cout << "first: " << iter->first << ", second: " << iter->second << "\n";
} else {
cout << "not found\n";
}
return 0;
}
prints
first: 4, second: 456
change my_set to just set<pair<int, int>> my_set; and it will print not found
Of course, keying only on first is arguably a map<int, int> so why not just do that?