An implementation of the dictionary (associative array) data structure in MQL5, based on CArrayObj and CList.
CDictionary *dict=new CDictionary();
//getting - variant 1
string variant1 = dict.Get<string>("costarring");
//getting - variant 2
double variant2 = 0;
It can also store pointers to objects (but not objects or structures):
Author: Enrico Lambino
Very nice work mate.
You're welcome. I uploaded as promised :)
Also, you were quite right about the serialization part. I overlooked the CreateElement() method in CArrayObj. It is only possible to save and load objects if you know in advance what type of objects to save and load, or if MQ introduces a new feature that converts string to generic type. That is why I uploaded with no Save() and Load() methods in it.
Very clever implementation. Nice work! I made some teaks to it to make it easier to work with (for my needs). Instead of holding multiple data-types this tweaked version only holds one but doesn't require specifying the data-type when calling the get method, and it also doesn't require a string key input since the key is templated and casts to string inside the dictionary class. Example:
if(dict[Time[i]] != Close[i])
Print("Collision Error ",++cnt);
Interesting version. Thank you for sharing your ideas.
The earlier versions of this class has Dictionary<T> on it. But later on I changed it. For my own needs, I needed a something where I can store various types of data at the same, but I can also see some applications where your version is better suited for the task (and less cumbersome, I agree).
Very nice work.
For me, I just don't understand the benefit of extending CArrayObj, as most things to do with CArrayObj are forbidden in CDictionary (like Sort() etc.) and can mess up in case of malusage.Actually, CDictionary is not a CArrayObj (defies the liskov principle of inheritance). So there is no real use of the CArrayObj.I would extend CObject instead and have m_data inside instead.
I assume that's because MQL doesn't allow
class SubClass : private SuperClass
Wrapping was my first choice.But then I noticed that it's not that trivial, as the m_data_max and m_data_total both protected in CArrayObj and have only a getter, and the algorithm needs a setter.The m_data_max also is used a little differently in CArrayObj.But anyway,
is allowed in MQL5, which can be a solution.The only reason I see to use CArrayObj is because of freeing memory, which is pretty simple to do. Because I don't see nothing else is used of CArrayObj.It is mostly used as CObject *m_data - and that is not a sufficient reason to extend it in my opinion.
I appreciate your inputs. I agree. Using CArrayObj is somewhat optional in this case. There are many alternatives. You can make the superclass private as you stated, or directly inherit from CObject (your sample code), or meet halfway: extend CArray instead of CArrayObj so it would be safe against accidental misuse (no actual sorting is done). Most of the needed methods from CArrayObj are not that difficult to re-implement. Mine is somewhat an opinionated solution (I chose to reuse as much code as I can for this class). Feel free to modify as you see fit.
for(int i=0;i<20;i++) //Bars(_Symbol,_Period);i++)
for(int i=0; node!=NULL; i++)
for(int i=0; node!=NULL; i++)
I've discovered a bug in CDictionary. When you use the Reset Method it deletes the CList object in m_data. Subsequent calls to other methods that fetch the point from the dictionary receive a bad pointer in return. Example:
I would propose the following fix for all methods which use the key hash to access a CList object from the m_data array.
bool CDictionary::Contains(string key)
if(CheckPointer(m_data[index]) == POINTER_INVALID)
m_data[index] = new CList;
CDictionaryEntryBase *model=new CDictionaryEntry<T>(key,value);