Dictionary in C++ using a Map with no values, only keys - c++

I'm implementing some sort of lookup for words in c++, and while the code for implementing a map is there, I wanna make sure if it works that using a map with keys and values as std::string, and using only keys as lookups without a value to return.
std::vector< std::string> DictionLines;
Reader DictionReader(Dictionary);
DictionLines = DictionReader.getLines();
std::map<std::string, std::string> DictionaryM;
for (int t = 0; t < DictionLines.size(); ++t) {
DictionaryM.insert(std::pair<std::string, std::string>(DictionLines.at(t), DictionLines.at(t)));
}
This code takes in the 349900 words in a Dictionary.txt file, and stores them in the map. Each line of the dictionary is just the word to lookup; no definition or any value to associate. Which is why I think just storing a pair of the same key and value in the map is ok, and using find and first/second would also be fine? Please confirm.

It looks like you want std::set. It is like a map where only keys matter and you never care or use the value. To look in a dictionary represented as a std::set<std::string> for some word after a given prefix, consider lower_bound
You should look more into C++ standard containers. There are not that much choice, and you should somehow know all of them (and choose or combine the right containers for the job)

Related

Best practices for searching in unordered_map

I want to create a std::unordered_map < int, std::string >
or std::unordered_map< std::string, int >.
In this map I will store strings and their integer representations.
I'll fill this map only in the code(hard coded pairs).
I'll need convert input strings to their int values - find in map.
So I only need to search in the map at the run time.
At this point I need the best performance while converting.
In the best case - O(1).
My questions:
Should I use string as key or int ?
Should I define my own hash-function ?
What is the best-performance find function for the both cases string/int and int/string as key-pairs?
std::map or std::unordered_map or their multi-counterparts all are built up the same - they map a key (first template parameter) to a value (second one). If you want to get O(1) (unordered) or O(log(n)) (map) behaviour, you need to define as key that data type you want to get a value for.
As you want to find an integral value for a given string, the way to go in your case is std::unordered_map<std::string, int>.
A counter-example would be looking up names for error codes, there you typically have a specific error code returned by a function (or placed in errno) and want to get a string value for e. g. for printing the error to console. Then you'd have std::unordered_map<int, std::string> (provided you could not store the error strings in an array because of error codes being too far distributed...).
Edit:
Defining your own hash function is that kind of premature optimisation Konstantin mentions in his comment - std::string provides its own hash code function, which should fit well for most of the use cases. Only if you discover that your hashing gets too slow, try to find a faster way.
As all your strings are hard-coded, you might want to have a look at perfect hashing, e. g. in the gperf variant.

Something like map but with one value?

I use map for fast finding names which can be about 200 and always different value or position. So now I write this :
map<string, string> names;
void function( string name)
{
names.insert(pair<string,string>(name,name));
}
So key and value always same. Is it good to use this or exist something better? I don't want to use vector because i often find names and vector always do this successively.
You're looking for std::set<std::string>. Sets are like maps, but with no satellite data, i.e. they only store the key.
If you don't need ordering, you may also try std::unordered_set<std::string>, which offers asymptotically faster lookup on average.

How do I create an std::map with multiple indices?

The following works:
std::map<std::string, Animal*> animalMap;
animalMap["KillerRabbit"] = new KillerRabit;
But what if I wanted to do this?
animalMap["KillerRabbit"]["White"] = new KillerRabit;
I have no idea what the 'official' name for the indices brackets are, knowing them would help immensely while Googling =p
What you are looking for is a map of maps:
std::map<std::string, std::map<std::string, Animal*>> animalMap;
Now each value stored in animalMap is itself a std::map. The key type for both the outer and inner maps are std::string.
The [...] syntax is the subscript operator. More specifically, though, you subscript a map with keys. Keys are mapped to values.
sftrabbit gives the canonical way to do it. If you don't want multiple map look ups per key you could also use std::pair as a map key.
Here is an example of doing it that way.

C++: insert into std::map without knowing a key

I need to insert values into std::map (or it's equivalent) to any free position and then get it's key (to remove/modify later). Something like:
std::map<int, std::string> myMap;
const int key = myMap.insert("hello");
Is it possibly to do so with std::map or is there some appropriate container for that?
Thank you.
In addition to using a set, you can keep a list of allocated (or free)
keys, and find a new key before inserting. For a map indexed by
int, you can simply take the last element, and increment its key. But
I rather think I'd go with a simple std::vector; if deletion isn't
supported, you can do something simple like:
int key = myVector.size();
myVector.push_back( newEntry );
If you need to support deletions, then using a vector of some sort of
"maybe" type (boost::optional, etc.—you probably already have
one in your toolbox, maybe under the name of Fallible or Maybe) might be
appropriate. Depending on use patterns (number of deletions compared to
total entries, etc.), you may want to search the vector in order to
reuse entries. If your really ambitious, you could keep a bitmap of the
free entries, setting a bit each time you delete and entry, and
resetting it whenever you reuse the space.
You can add object to an std::set, and then later put the whole set into a map. But no, you can't put a value into a map without a key.
The closest thing to what you're trying to do is probably
myMap[myMap.size()] = "some string";
The only advantage this has over std::set is that you can pass the integer indexes around to other modules without them needing to know the type of std::set<Foo>::iterator or similar.
It is impossible. Such an operation would require intricate knowledge of the key type to know which keys are available. For example, std::map would have to increment int values for int maps or append to strings for string maps.
You could use a std::set and drop keying altogether.
If you want to achieve something similar to automatically generated primary keys in SQL databases than you can maintain a counter and use it to generate a unique key. But perhaps std::set is what you really need.

Could not Understand the usage of map in c++

Map is a container class that is used to store the aggregate data... Its very easy to retreive the datas stored in it as it uses hash algorithm for retrieval.
map is a key value pair...The data can be retrieved with the corresponding key...
Here in this declaration below I'm defining that the key has to be integer(4 bytes) and data as the string value...
typedef map<INT32U,string> EventMapType;
I searched for the example program of using map in wikipedia... But i could not understand the example given over there..I need to know how the datas and keys are stored in the map and how it is retreived through the key...I am new to MFC...
Beata,
I just did a quick google and came up with http://erunways.com/c-using-the-standard-template-library-stl-map-example/ I won't just copy paste that code here... it's only about 50 lines.
I suggest you read through that code, and then compile and run it (as is). If you run into problems or just stuff that doesn't make sense to you, then ask specific questions here. K?
Cheers. Keith.
map does not use hashing. It can't, because the constraints do not require hashable keys. It is ordinarily implemented as a binary search tree, sorted by key. Thus, it requires keys be <-comparable
In contrast, C++0x will provide an unordered_map, which does use hashing.
If you want specific help, you should tell us what code you've tried so far, and which examples you don't understand.
the STL's map class allows you to store data by any type of key instead of simply by a numerical key, the way you must access an array or vector. So instead of having to compute a hash function and then access an array, you can just let the map class do it for you.
typedef map<INT32U,string> MyEventMapType;
MyEventMapType EventMapType;
Use below as reference code.
To Store values :
EventMapType[key1] = string1 ;
EventMapType[key2] = string2 ;
EventMapType[key3] = string3 ;
To check the value at key1 ...
if(EventMapType.find("key1") == EventMapType.end())
{
std::cout<<"string1 is not in the map!"<<endl;
}
For more read the documentation
Iterators can also be used as a general means for accessing the data stored in a map; you can use the basic technique from before of getting an iterator: