i want to see the number of appearance of words from some phrases.
My problem is that i can't use map to do this:
map[word] = appearnce++;
Instead i have a class that uses binary tree and behaves like a map, but i only have the method:
void insert(string, int);
Is there a way to counts the words apperances using this function?(because i can't find a way to increment the int for every different word) Or do I have to overload operator [] for the class? What should i do ?
Presumably you also have a way to retrieve data from your map-like structure (storing data does little good unless you can also retrieve it). The obvious method would be to retrieve the current value, increment it, and store the result (or store 1 if retrieving showed the value wasn't present previously).
I guess this is homework and you're learning about binary trees. In that case I would implement operator[] to return a reference to the existing value (and if no value exists, default construct a value, insert it, and return that. Obviously operator[] will be implemented quite similarly to your insert method.
can you edit "insert" function?
if you can, you can add static variable that count the appearnces inside the function
Related
I need a function that needs to check if the input (std::string) is unique and return its corresponding enum value.
I already have been able to implement this function with just a simple vector, which checks if the input is unique.
it should return enumE::HELLO.
I tried to adapt the code above for the vector to suit this function, but I am not really getting anywhere.
Based on the description of your example, here is a quick implementation. Of course, the logic may not be entirely what you wrote, but I am sure you can tweak it.
Why would you iterate through the whole string if std::string has a std::string::find function which will find a substring for you?
Is it necessary to go through all the trouble you wrote above? Does the code need to be that dense and unreadable?
Feel free to play around with that function and implement your logic.
Let's have a collection of objects (say string is type of collection). I want each element of collection to have a reference count. So, on Add-Usage it should increment count for this given element.
coll.AddUsage("SomeElement"); // Type doesn't matter - but should increase count
On, Release-Usage, it should decrement the reference count for given element, and if count reaches 0, then it should remove the element from collection.
It is not important if AddUsage will allocate element (and set reference-count to 1), or would fail altogether (since element didn't exist). Important thing is RemoveUsage, which should remove given element (object) from collection.
I thought of using vector of a pair (or a custom struct), or using any kind of map/multimap. There exists no existing class in C++ library (may be out of thread-support library, one atomic classes, shared-pointer classes etc).
Question:
So, my question is how to implement such idea, using existing C++ library? It should be thread safe. Yes, C++11/14 is perfectly okay for me. If good idea is there, I would probably craft it on top of templates.
Assuming you ask for a data structure to implement your reference-counting collection...
Use a map<K,V> with K as the type of collection elements (in your example string) and V a type to keep track of meta-information about the element (e.g. reference count). The simplest case is when V is int.
Then, AddUsage is simple, just do refMap[value]++. For RemoveUsage just do a refMap[value]--, then check if the counter hit zero and remove the value from the map.
You need to add error handling too, since AddUsage / RemoveUsage may be
called with an object which is not in the map (not added to the collection)
EDIT: You tagged your question with "multithreading", so you probably want to have a mutex of some sort which guards the concurrent access to refMap.
You could implement something similar to shared_ptr class but extending it to hold collection of objects.
Like you could design a class with map/multimap as its data member. Key would be your object and value be your reference count.As far as interface is concerned just expose two methods:-
AddUsage(Object);
RemoveUsage(Object);
In your AddUsage method you would first check if element already exists in map.If yes then only increment the count. Likewise you would handle RemoveUsage.Object would be deleted from map if its reference count reaches zero.
This is just my opinion. Please let me know if there are any bottlenecks in this implementation.
You can use static member(integer) variable in the structure or class. Increment or decrement whereever you want. Remove the element if the value is zero.
I often see code like:
if(myQMap.contains("my key")){
myValue = myQMap["my key"];
}
which theoretically performs two look-up's in the QMap.
My first reaction is that it should be replaced by the following, which performs one lookup only and should be two times faster:
auto it = myQMap.find("my key");
if(it != myQMap.end()){
myValue = it.value();
}
I am wondering if QMap does this optimization automatically for me?
In other words, I am wondering if QMap saves the position of the last element found with QMap::contains() and checks it first before performing the next lookup?
I would expect that QMap provides both functions for a better interface to the class. It's more natural to ask if the map 'contains' a value with a specified key than it is to call the 'find' function.
As the code shows, both find and contains call the following internal function: -
Node *n = d->findNode(akey);
So if you're going to use the returned iterator, then using find and checking the return value will be more efficient, but if you just want to know if the value exists in the map, calling contains is better for readability.
If you look at the source code, you'll see that QMap is implemented as a binary tree structure of nodes. Calling findNode iterates through the nodes and does not cache the result.
QMap source code reveals that there is no special code in QMap::contains() method.
In some cases you can use QMap::value() or QMap::values() to get value for a key and check if it is correct. These methods (and const operator[]) will copy the value, although this is probably OK for most Qt types since their underlying data are copied-on-write (notably QMap itself).
I have a certain struct:
struct MyClass::MyStruct
{
Statistics stats;
Oject *objPtr;
bool isActive;
QDateTime expiration;
};
For which I need to store pointers to in a private container. I will be getting objects from client code for which I need to return a pointer to the MyStruct. For example:
QList<MyStruct*> MyClass::structPtr( Statistics stats )
{
// Return all MyStruct* for which myStruct->stats == stats (== is overloaded)
}
or
QList<MyStruct*> MyClass::structPtr( Object *objPtr )
{
// Return all MyStruct* for which myStruct->objPtr == objPtr
}
Right now I'm storing these in a QLinkedList<MyStruct*> so that I can have fast insertions, and lookups roughly equivalent to QList<MyStruct*>. Ideally I would like to be able to perform lookups faster, without losing my insertion speed. This leads me to look at QHash, but I am not sure how I would use a QHash when I'm only storing values without keys, or even if that is a good idea.
What is the proper Qt/C++ way to address a problem such as this? Ideally, lookup times should be <= log(n). Would a QHash be a good idea here? If so, what should I use for a key and/or value?
If you want to use QHash for fast lookups, the hash's key type must be the same as the search token type. For example, if you want to find elements by Statistics value, your hash should be QHash<Statistics, MyStruct*>.
If you can live with only looking up your data in one specific way, a QHash should be fine for you. Though, in your case where you're pulling lists out, you may want to investigate QMultiHash and its .values() member. However, it's important to note, from the documentation:
The key type of a QHash must provide operator==() and a global hash function called qHash()
If you need to be able to pull these lists based on different information at different times you might just be better off iterating over the lists. All of Qt's containers provide std-style iterators, including its hash maps.
I have a settings which are stored in std::map. For example, there is WorldTime key with value which updates each main cycle iteration. I don't want to read it from map when I do need (it's also processed each frame), I think it's not fast at all. So, can I get pointer to the map's value and access it? The code is:
std::map<std::string, int> mSettings;
// Somewhere in cycle:
mSettings["WorldTime"] += 10; // ms
// Somewhere in another place, also called in cycle
DrawText(mSettings["WorldTime"]); // Is slow to call each frame
So the idea is something like:
int *time = &mSettings["WorldTime"];
// In cycle:
DrawText(&time);
How wrong is it? Should I do something like that?
Best use a reference:
int & time = mSettings["WorldTime"];
If the key doesn't already exist, the []-access will create the element (and value-initialize the mapped value, i.e. 0 for an int). Alternatively (if the key already exists):
int & time = *mSettings.find("WorldTime");
As an aside: if you have hundreds of thousands of string keys or use lookup by string key a lot, you might find that an std::unordered_map<std::string, int> gives better results (but always profile before deciding). The two maps have virtually identical interfaces for your purpose.
According to this answer on StackOverflow, it's perfectly OK to store a pointer to a map element as it will not be invalidated until you delete the element (see note 3).
If you're worried so much about performance then why are you using strings for keys? What if you had an enum? Like this:
enum Settings
{
WorldTime,
...
};
Then your map would be using ints for keys rather than strings. It has to do comparisons between the keys because I believe std::map is implemented as a balanced tree. Comparisons between ints are much faster than comparisons between strings.
Furthermore, if you're using an enum for keys, you can just use an array, because an enum IS essentially a map from some sort of symbol (ie. WorldTime) to an integer, starting at zero. So then do this:
enum Settings
{
WorldTime,
...
NumSettings
};
And then declare your mSettings as an array:
int mSettings[NumSettings];
Which has faster lookup time compared to a std::map. Reference like this then:
DrawText(mSettings[WorldTime]);
Since you're basically just accessing a value in an array rather than accessing a map this is going to be a lot faster and you don't have to worry about the pointer/reference hack you were trying to do in the first place.