Библиотеки: CDictionary class

 

CDictionary class:

Реализация словаря (ассоциативного массива) на MQL5 на основе CArrayObj и CList.

Автор: Enrico Lambino

 

Привет, Энрико,

Очень хорошая работа, дружище.

Спасибо,

Шеп

 
Shephard Mukachi:

Привет, Энрико,

Очень хорошая работа, приятель.

Спасибо,

Шеп

Не за что. Я загрузил, как и обещал :)

Кроме того, вы были совершенно правы насчет сериализации. Я упустил из виду метод CreateElement() в CArrayObj. Сохранять и загружать объекты можно только в том случае, если вы заранее знаете, какой тип объектов нужно сохранять и загружать, или если 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/ru/articles/1334

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

Очень хорошая работа.

Для меня только непонятно, какая польза от расширения CArrayObj, так как большинство вещей, которые можно сделать с CArrayObj, запрещены в CDictionary (например, Sort() и т.д.) и могут испортиться при неправильном использовании.
На самом деле CDictionary не является CArrayObj (противоречит лисковскому принципу наследования). Так что реальной пользы от CArrayObj нет.
Я бы вместо этого расширил CObject и имел бы внутри m_data[].

*-Новая версия DictionarySingle: Добавлена последовательная итерация и управление памятью, проведена незначительная рефакторинг
Файлы:
 
Amir Yacoby:

Очень хорошая работа.

Для меня только непонятно, какая польза от расширения CArrayObj, так как большинство вещей, которые можно сделать с CArrayObj, запрещены в CDictionary (например, Sort() и т.д.) и могут испортиться при неправильном использовании.
На самом деле CDictionary не является CArrayObj (противоречит лисковскому принципу наследования). Так что реального использования CArrayObj нет.
Я бы вместо этого расширил CObject и имел бы внутри m_data[].

Я предполагаю, что это потому, что MQL не позволяет

class SubClass : private SuperClass


Но не нужно выплескивать ребенка вместе с водой. Вы можете просто обернуть объект CArrayObj вместо того, чтобы реализовывать его через деривацию.
 
nicholishen:

Я предполагаю, что это потому, что MQL не позволяет

class SubClass : private SuperClass


Но не нужно выплескивать ребенка вместе с водой. Можно просто обернуть объект CArrayObj вместо того, чтобы реализовывать его через деривацию.

Обертывание было моим первым выбором.
Но потом я заметил, что это не так уж тривиально, поскольку m_data_max и m_data_total оба защищены в CArrayObj и имеют только геттер, а алгоритму нужен сеттер.
m_data_max также используется немного по-другому в CArrayObj.

Но в любом случае,

class SubClass : private SuperClass

разрешен в MQL5, что может быть решением.
Единственная причина, по которой я вижу необходимость использовать CArrayObj - это освобождение памяти, что довольно просто сделать.
Потому что я не вижу, чтобы CArrayObj использовался как-то иначе.

В основном он используется как CObject *m_data[] - и это, на мой взгляд, не является достаточной причиной для его расширения.

 
Amir Yacoby:

Обертывание было моим первым выбором.
Но потом я заметил, что все не так тривиально, поскольку m_data_max и m_data_total защищены в CArrayObj и имеют только геттер, а алгоритму нужен сеттер.
m_data_max также используется немного иначе в CArrayObj.

Но в любом случае,

разрешен в MQL5, что может быть решением.
Единственная причина, по которой я вижу необходимость использовать 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();
     }
Файлы: