程序库: CDictionary

 

CDictionary:

使用 MQL5 实现的字典(关联数组)数据结构,基于 CArrayObj 和 CList。

作者: Enrico Lambino

 
Automated-Trading:

CDictionary 类

作者: Enrico Lambino恩里科-兰比诺

你好,恩里科、

干得漂亮,伙计。

谢谢、

谢普

 
Shephard Mukachi:

你好,恩里科、

干得漂亮,伙计。

谢谢、

谢泼

不客气。我已经按约定上传了)

另外,关于序列化部分,你说得很对,我忽略了 CArrayObj 中的 CreateElement() 方法。只有事先知道要保存和加载什么类型的对象,或者 MQ 推出了将字符串转换为通用类型的新功能,才有可能保存和加载对象。这就是为什么我在上传时没有使用 Save() 和 Load() 方法。

 

非常巧妙的实施。干得漂亮!我对它做了一些调整,使它更易于使用(满足我的需要)。这个经过调整的版本不再保存多种数据类型,而是只保存一种,但在调用 get 方法时不需要指定数据类型,也不需要输入字符串键,因为键是模板化的,并在字典类中转换为字符串。示例


   CDictionary<double> dict;
   for(int i=0;i<Bars;i++)
      dict.Add(Time[i],Close[i]);
   for(int i=0;i<Bars;i++)
      if(dict[Time[i]] != Close[i])
         Print("Collision Error ",++cnt); 
附加的文件:
Dictionary.mqh  16 kb
 
nicholishen:

非常巧妙的实施。干得漂亮!我对它做了一些修改,使它更易于使用(满足我的需要)。这个经过调整的版本不再保存多种数据类型,而是只保存一种,但在调用 get 方法时不需要指定数据类型,也不需要输入字符串键,因为键是模板化的,并在字典类中转换为字符串。示例


有趣的版本。感谢您分享您的想法。

该类的早期版本包含 Dictionary<T>。但后来我改变了它。根据我自己的需要,我需要一个可以同时存储各种类型数据的东西,但我也可以看到在某些应用中,你的版本更适合完成任务(而且我同意,不会那么繁琐)。

 

作为补充,我使用 @Vasiliy Sokolov 提供的同名类,效果很好。我刚看到这个,现在下载吧

https://www.mql5.com/zh/articles/1334

Рецепты MQL5 - Реализуем ассоциативный массив или словарь для быстрого доступа к данным
Рецепты MQL5 - Реализуем ассоциативный массив или словарь для быстрого доступа к данным
  • 2015.03.23
  • Vasiliy Sokolov
  • www.mql5.com
Эта статья описывает удобный класс для хранения информации - ассоциативный массив или словарь. Благодаря этому классу можно получать доступ к информации по ее ключу. Ассоциативный массив напоминает обычный массив, однако вместо индекса он использует некий уникальный ключ, например, перечисление ENUM_TIMEFRAMES или какой-либо текст. Что...
 

干得漂亮


事实上,CDictionary 并不是一个CArrayObj(违背了继承的利斯科夫原则),所以它并没有真正使用 CArrayObj。因此,CArrayObj 并没有真正的用途。
,我会扩展 CObject,并在其中加入 m_data[]。

*-新版 DictionarySingle:添加了串行迭代和内存管理,并进行了一些小的重构
附加的文件:
 
Amir Yacoby:

干得漂亮


事实上,CDictionary 并不是一个 CArrayObj(违背了继承的利斯科夫原则),所以它并没有真正使用 CArrayObj。因此,CArrayObj 并没有真正的用途。
,我会扩展 CObject,并在其中使用 m_data[]。

我想这是因为 MQL 不允许

class SubClass : private SuperClass


但没必要把孩子和洗澡水一起倒掉。你可以简单地封装一个CArrayObj 对象,而不是通过派生来实现它。
 
nicholishen:

我想这是因为 MQL 不允许

class SubClass : private SuperClass


但没必要把孩子和洗澡水一起倒掉。您可以简单地封装一个 CArrayObj 对象,而不是通过派生来实现它。


但后来我注意到这并不那么简单,因为在 CArrayObj 中,m_data_max 和 m_data_total 都是受保护的,并且只有一个 getter,而算法需要一个 setter。
在 CArrayObj 中,m_data_max 的使用方式也有些不同。

但无论如何、

class SubClass : private SuperClass


我认为使用 CArrayObj 的唯一原因是为了释放内存,这很容易做到。
因为我没有看到 CArrayObj 的其他用途。

它主要用作 CObject *m_data[] - 在我看来,这不是扩展它的充分理由。

 
Amir Yacoby:


但后来我注意到这并不那么简单,因为 m_data_max 和 m_data_total 在 CArrayObj 中都是受保护的,并且只有一个 getter,而算法需要一个 setter。
m_data_max 在 CArrayObj 中的使用方式也有些不同。

但不管怎样、


我认为使用 CArrayObj 的唯一原因是为了释放内存,而这是非常简单的。
因为我没有看到 CArrayObj 的其他用途。

它主要用作 CObject *m_data[] - 在我看来,这不是扩展它的充分理由。

感谢您的意见。我同意。在这种情况下,使用CArrayObj 有点可有可无。
有很多替代方法。你可以像你所说的那样将超类私有化,或者直接从 CObject 继承(你的示例代码),或者半途而废:扩展 CArray 而不是 CArrayObj,这样就可以避免意外误用(不会进行实际排序)。
重新实现 CArrayObj 所需的大多数方法并不困难。我的解决方案有些主观臆断(我选择尽可能多地重用该类的代码)。
请随意修改。

 
更新了 DictionarySingle 版本 - 按对象添加顺序添加了序列迭代,添加了内存自动管理,并进行了少量重构。
迭代示例:
   CDictionary<double> dict;
    datetime time[];
   double close[];
   ulong bars=Bars(_Symbol,_Period);
   ArraySetAsSeries(time,true);
   ArraySetAsSeries(close,true);
   CopyTime(_Symbol,_Period,0,Bars(_Symbol,_Period),time);
   CopyClose(_Symbol,_Period,0,Bars(_Symbol,_Period),close);
   for(int i=0;i<20;i++) //Bars(_Symbol,_Period);i++)
     {
      dict.Add(time[i],close[i]);
      //dict.Add(time[i],close[i]*100);
     }

   //--- 转发
   CDictionaryEntry<string> *node=dict.GetFirstNode();
   for(int i=0; node!=NULL; i++)
     {
      printf((string)i+":\t"+node.Value());
      node=dict.GetNextNode();
     }
   //--- 后退
   node=dict.GetLastNode();
   for(int i=0; node!=NULL; i++)
     {
      printf((string)i+":\t"+node.Value());
      node=dict.GetPrevNode();
     }
附加的文件: