C++: map<wstring,wstring> Getting second from first - c++

I have a
map <wstring,wstring>.
I have inserted pairs like this:
m_Translations.Content().insert(pair<wstring,wstring>(L"rome",L"roma"));
m_Translations.Content().insert(pair<wstring,wstring>(L"water",L"aqua"));
How could I determine the translation for "water" from the map?
In other words: I would like to get the second item from the first.
The search is case-sensitive.
Thank you for the help!

A bit weird question. What about the default way of accessing a map with operator[]?
wstring aqua = m_Translations.Content()[L"water"];
In case you are not sure whether a translation exists or not, you can check it with the find method:
const auto& dict = m_Translations.Content();
auto pAqua = dict.find(L"water");
if (pAqua != dict.end())
{
// Found it!
}
else
{
// Not there...
}

You can use operator[] available on std::map.
For example:
map<wstring, wstring> myMap = m_Translations.Content();
myMap.insert(pair<wstring, wstring>(L"rome", L"roma"));
myMap.insert(pair<wstring, wstring>(L"water", L"aqua"));
// waterText value would be 'aqua'
wstring waterText = myMap[L"water"];

Related

Retrieve first key of std::multimap, c++

I want to retrieve just the first key of a multimap. I already achieved it with iterating through the multimap, taking the first key and then do break. But there should be a better way, but I do not find it.
int store_key;
std::multimap<int, int> example_map; // then something in it..
for (auto key : example_map)
{
store_key = key;
break;
}
This solves the Problem, but I am searching for another solution.
Your range based for loop is more or less (not exactly but good enough for this answer) equivalent to:
for (auto it = example_map.begin(); it != example_map.end(); ++it) {
auto key = *it;
store_key = key;
break;
}
I hope now it is clear that you can get rid of the loop and for a non-empty map it is just:
auto store_key = *example_map.begin();
Note that store_key is a misnomer, because it is not just the key and your code would trigger a compiler error. It is a std::pair<const int,int>. store_key->first is the key.

Moving object to front of vector pair string c++

I have a question about moving an Object to the front in a vector pair. I already read that one post but I didnt know how to use it with vector pairs or better said how to do it with strings. I dont know how to point with an iterator at the position I need because in my code I also need a count number to compare the two strings or how is it possible to compare something like if(it==ite){..} (i would need 2 loops for my examples so I would name the other one "ite" just as an example.
I have a vector<pair<string,string>> Dictionary and a vector string Text where I go through the dictionary and try to find the same word from the text in the dictionary. I already accomplished that but now I need to move the element that I found in the dictionary to the front and delete it from its old position.
I´m not sure how to do it with vector pairs.
Here´s my code to understand what I mean:
for(size_t i=0;i<Text.size();i++){
for(size_t j=0;j<Duden.size();j++){
if(Text[i]==Duden[j].first){
uebersetzung.push_back(Duden[j].first);
if(Duden[j].first.length()<4){
uebersetzung.push_back(" ");}
if(Duden[j].first.length()<8){
uebersetzung.push_back("\t");} // These are only so it looks cleaner at the end
uebersetzung.push_back("\t\t\t\t: ");
uebersetzung.push_back(Duden[j].second);
uebersetzung.push_back("\n");
// Now here should be the code to rotate the vector so the found element is now at the first position and not at the found position
break;
}
}
}
"Duden" here is dictionary if you´re wondering. I want to swap position of the elements from the dictionary so if the word occurs again in the text it doesnt need to go trough the whole dictionary again and instead just find it directly in the first positions.
How can I accomplish that with using rotate? Or do I need to do it with erase and insert because rotate doesnt work with pairs of vectors?
Consider making use of algorithms in the STL library. To use them, you have to get familiar with iterators. Then you can use something like std::rotate and it does not really matter what is in your vector.
For example your code can be refactored in the following way:
for (auto const& word : Text) {
auto it = std::find(Duden.begin(), Duden.end(), [&word](auto const& entry) {
return entry.first == word;
});
if(it == Duden.end()) {
continue;
}
generate_translation(uebersetzung, *it);
std::rotate(Duden.begin(), it, it+1);
}
The function generate_translation(std::vector<string>&, std::pair<string, string> const&) should be an own function to make the code more readable.
Something like
void generate_translation(std::vector<string>& uebersetzung,
std::pair<string, string> const& entry)
{
uebersetzung.push_back(entry.first);
if(entry.first.length() < 4){
uebersetzung.push_back(" ");
}
if(entry.first.length() < 8){
uebersetzung.push_back("\t");
} // These are only so it looks cleaner at the end
uebersetzung.push_back("\t\t\t\t: ");
uebersetzung.push_back(entry.second);
uebersetzung.push_back("\n");
}

How to modify every value in unordered map in c++

I have a unordered map (umap) in C++ :
unordered_map<int, bool> dTimeResetUmap;
I am setting its value like:
dTimeResetUmap[person.object_id] = true;
person.object_id can be 0, 1, 2, 3 any int number. At certain point in code, I have to modify the al the values in it (basically have to make all the values as false) which I am doing like below:
int size_of_dTimeResetUmap = dTimeResetUmap.size();
for (int i = 0; i <= size_of_dTimeResetUmap; i++)
{
dTimeResetUmap[i] = false;
}
But it seems not to be working for some value. After a long run of code, there are few values inside dTimeResetUmap which remains true instead of false. What can be the reason. Is it not a good way of updating values. Please help Thanks.
Use C++ iterations to visit each element of map:
for (auto & element : dTimeResetUmap)
{
element.second = false;
}
If you use the indexing operator [] to access a value in the map, and the key isn't in the map, then a new key-value pair will be created, with a default "zero" value.
For a bool value, this "zero" will be equal to false.
So the simplest way to set all elements to false is to just remove all elements as then all access to the non-existing keys will create false values:
dTimeResetUmap.clear();
You can use STL iterators;
for (auto it = umap.begin(); it != umap.end(); it++) {
(*it).second = false;
}

Can anyone help me make this function more efficient

So I am trying to sort through an unordered_map container. The container reads input from a file which is a list of people. Each line in the file will be like rCB, bIA, and this will be stored as an element in the map. The second string in each element acts as a pointer to the next person in the list, so later on it will appear again in a new line, in this case:bIA,TDV.
So far I can sort through in order by creating an unordered_map iterator and using the second string in the find function for the iterator to go to the next element. My problem is going the other way. I am able to sort through the opposite way but the way i have implemented my solution means that it takes a very long time to eventually sort through, as we have input files of 3 million people.
list<string> SortEast(unordered_map<string, string> &TempUMap, unordered_map<string, string>::iterator IT, list<string> &TempList)
{
IT = TempUMap.begin();
while (TempList.size() != (TempUMap.size() + 1))
{
if (IT->second == TempList.front())
{
TempList.emplace_front(IT->first);
IT = TempUMap.begin();
}
IT++;
}
return TempList;
}
I've tried to make this more efficient but I cannot think of how. If i could find the value that would go at the start of the list I could sort in order starting with that value, but again I dont know how I would find this value easily.
Any help would be appreciated.
EDIT:
A sample of one of our input is:
rBC,biA
vnN,CmR
CmR,gnz
Dgu,OWn
lnh,Dgu
OWn,YMO
YMO,SIZ
XbL,Cjj
TDV,jew
iVk,vnN
wTb,rBC
jew,sbE
sbE,iVk
Cjj,wTb
AGn,XbL
gnz,SMz
biA,TDV
SIZ,uvD
SMz,lnh
This is only 20 people. In this case AGn is the first value and uvD is the last. The output I end up with is:
AGn
XbL
Cjj
wTb
rBC
biA
TDV
jew
sbE
iVk
vnN
CmR
gnz
SMz
lnh
Dgu
OWn
YMO
SIZ
uvD
As this file starts with rBC, that is the point at which i need to sort backwards
Can you not simply do something like this:
vector<string> orderAllTheNames(const unordered_map<string, string>& input, const string& begin)
{
vector<string> result;
result.reserve(input.size());
string current = begin;
result.push_back(current);
while(result.size() < input.size())
{
current = input[current];
result.push_back(std::move(current));
}
return result;
}
I may have missed some details as I typed this on my phone. You can add some pointers and/or std::moves if you're worried about too many copies flying around.
I guess it's the same as your solution, but without the awkward list and emplace_front.

Is there a way to get a node via a Map value in LEMON Graph library?

I am the using LEMON Graph library and was wondering if there is an efficient way to receive a ListDigraph::Node x via the value of its corresponding ListDigraph::NodeMap?
I was thinking about something like:
lemon::ListDigraph lg;
lemon::ListDigraph::NodeMap<std::string> nodeColor(lg);
lemon::ListDigraph::Node n = lg.addNode();
nodeColor[n] = "red";
lemon::ListDigraph::Node m = lg.addNode();
nodeColor[m] = "green";
# now I'd like to have something like:
lemon::ListDigraph::Node x = nodeColor.getNodeFromColor("red");
Does something like this already exist in LEMON? If there is no other way than writing my own map, how do I return the key (Node)? Can I iterate over the underlying values of the map?
Unfortunately, it is not possible to obtain the keyset (or the respective nodes) from Lemon's NodeMap, see the NodeMap reference.
There is also no way to iterate over the map. The best way to overcome this is to write your own map, as you write yourself, or use additional helper maps (or similar containers).
As far as I know, that's not possible in Lemon out of the box. In particular, because the NodeMap is not necessarily one-to-one. There is nothing stopping you from giving all nodes the value "red", and so the backwards query would not have a unique correct result.
You also cannot directly iterate over the contents of a NodeMap. You can, however, iterate over all nodes in the graph, and ask for the corresponding values:
for (lemon::ListDigraph::NodeIt n(lg); n != lemon::INVALID; ++n) {
if (nodeColor[n] == "red) {
// do something
}
}
Or, as you mentioned, you can define your own map:
#include <unordered_map>
lemon::ListDigraph lg;
lemon::ListDigraph::NodeMap<std::string> nodeColor(lg);
std::unordered_map<std::string, lemon::ListDigraph::Node> color2node;
lemon::ListDigraph::Node n = lg.addNode();
nodeColor[n] = "red";
color2node.emplace("red", n);
lemon::ListDigraph::Node m = lg.addNode();
nodeColor[m] = "green";
color2node.emplace("green", m);
lemon::ListDigraph::Node x = node2color.at("red");