Обсуждение статьи "Рецепты MQL5 - Реализуем ассоциативный массив или словарь для быстрого доступа к данным"
Опубликована статья Рецепты MQL5 - Реализуем ассоциативный массив или словарь для быстрого доступа к данным:
Автор: Vasiliy Sokolov
Крутая работа, автору респект! Это то, что давно должны были включить MQ в \MQL5\Include\Arrays, надеюсь, это войдет в библиотеку в следующих релизах. Кстати, на MQL4 также все отлично работает, вот замеры по первому тесту. Я так понимаю, простые типа данных включить вместо *CObject не получиться из-за отсутствия полноценных указателей? Или как-то можно извернуться?
2015.03.23 13:25:54.617 TestDict EURUSD,M1: 1000000 elements. Add: 1373; Get: 218 2015.03.23 13:25:52.644 TestDict EURUSD,M1: 950000 elements. Add: 1216; Get: 219 2015.03.23 13:25:50.833 TestDict EURUSD,M1: 900000 elements. Add: 1217; Get: 218 2015.03.23 13:25:49.069 TestDict EURUSD,M1: 850000 elements. Add: 1154; Get: 187 2015.03.23 13:25:47.424 TestDict EURUSD,M1: 800000 elements. Add: 1092; Get: 187 2015.03.23 13:25:45.844 TestDict EURUSD,M1: 750000 elements. Add: 1061; Get: 171 2015.03.23 13:25:44.320 TestDict EURUSD,M1: 700000 elements. Add: 1107; Get: 156 2015.03.23 13:25:42.761 TestDict EURUSD,M1: 650000 elements. Add: 1045; Get: 140 2015.03.23 13:25:41.304 TestDict EURUSD,M1: 600000 elements. Add: 1014; Get: 156 2015.03.23 13:25:39.915 TestDict EURUSD,M1: 550000 elements. Add: 920; Get: 125 2015.03.23 13:25:38.665 TestDict EURUSD,M1: 500000 elements. Add: 702; Get: 109 2015.03.23 13:25:37.693 TestDict EURUSD,M1: 450000 elements. Add: 593; Get: 93 2015.03.23 13:25:36.836 TestDict EURUSD,M1: 400000 elements. Add: 577; Get: 78 2015.03.23 13:25:36.025 TestDict EURUSD,M1: 350000 elements. Add: 561; Get: 78 2015.03.23 13:25:35.247 TestDict EURUSD,M1: 300000 elements. Add: 515; Get: 78 2015.03.23 13:25:34.557 TestDict EURUSD,M1: 250000 elements. Add: 343; Get: 63 2015.03.23 13:25:34.063 TestDict EURUSD,M1: 200000 elements. Add: 312; Get: 47 2015.03.23 13:25:33.632 TestDict EURUSD,M1: 150000 elements. Add: 281; Get: 31 2015.03.23 13:25:33.264 TestDict EURUSD,M1: 100000 elements. Add: 171; Get: 16 2015.03.23 13:25:33.038 TestDict EURUSD,M1: 50000 elements. Add: 47; Get: 16
Крутая работа, автору респект! Это то, что давно должны были включить MQ в \MQL5\Include\Arrays, надеюсь, это войдет в библиотеку в следующих релизах. Кстати, на MQL4 также все отлично работает, вот замеры по первому тесту. Я так понимаю, простые типа данных включить вместо *CObject не получиться из-за отсутствия полноценных указателей? Или как-то можно извернуться?
Получиться. С помощью механизма boxing/unboxing и шаблонов. Идея в том, что каждый базовый тип запаковывается в контейнер KeyValuePairBase. Распаковка и возврат соответствующего типа производится внутренними функциями типа GetObjectByKey:
template<typename Type, typename T>
Type GetObjectByKey(T key);
Важно подчеркнуть, что работа с базовыми типами не даст преимущества в плане производительности, зато будет существенно удобней.
Сейчас попытался на основе шаблонов создать CDictionaryBase хранящий вместо CObject один из базовых типов MQL. К сожалению сделать этого не получилось, функции не позволяют возвратить шаблонный тип. А жаль:
//+------------------------------------------------------------------+ //| TestDictBase.mq5 | //| Copyright 2015, Vasiliy Sokolov. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Vasiliy Sokolov." #property link "http://www.mql5.com" #property version "1.00" #include <Dictionary.mqh> #include <DictionaryBase.mqh> //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- CDictionaryBase base; base.AddValue("Pi", 3.14159); double pi = (double)base.GetValueByKey("Pi"); printf(DoubleToString(pi, 5)); //base.AddObject( } //+------------------------------------------------------------------+
could not deduce template argument #1 TestDictBase.mq5 19 29 could not deduce template argument #0 DictionaryBase.mqh 404 25 possible loss of data due to type conversion DictionaryBase.mqh 133 10 possible loss of data due to type conversion DictionaryBase.mqh 135 10 possible loss of data due to type conversion DictionaryBase.mqh 137 10 ...
//+------------------------------------------------------------------+ //| Возвращет объект по ключу. | //+------------------------------------------------------------------+ template<typename T, typename C> C CDictionaryBase::GetValueByKey(T key) { if(!ContainsKey(key)) return NULL; return m_current_kvp.GetValue(); }
Жаль.
Значит, для каждого базового типа придется создавать свой базовый контейнер, либо просто создать контейнеры базовых типов: CDouble, CLong, CInt и т.д.
Сейчас попытался на основе шаблонов создать CDictionaryBase хранящий вместо CObject один из базовых типов MQL. К сожалению сделать этого не получилось, функции не позволяют возвратить шаблонный тип.
Позволяют. Но тип возвращаемого значения не может быть автоматически выведен, что собственно компилятор и пишет.
Можно использовать небольшой костылик в виде псевдопараметра.
template<typename T, typename C> C CDictionaryBase::GetValueByKey(T key, C) { if(!ContainsKey(key)) return NULL; return m_current_kvp.GetValue(); }
Позволяют. Но тип возвращаемого значения не может быть автоматически выведен, что собственно компилятор и пишет.
Можно использовать небольшой костылик в виде псевдопараметра.
А где собственно костылек?
Добавился второй параметр
Не пробовали сравнить быстродействие. С какого размера данных начинается преимущество по сравнению с бинарным поиском в отсортированном строковом массиве?
Точных тестов не производил, но по моим наблюдениям преимущество в скорости начинают проявляться начиная от десятков тысяч элементов. Т.е. в повседневных задачах на 100 - 10 000 элементов выигрыш в производительности не получить.
Здесь важно другое, а именно удобство работы с контейнером. Не нужно писать дополнительные методы по поиску элементов. Многие повседневные задачи со словарями становятся в разы проще в реализации. Не нужно создавать элемент для поиска индекса, затем извлекать нужный по соответствующему индексу и т.д. и т.п.
з.ы. Хотя тут подумалось, что производительность надо измерять как совокупное время на вставку элементов и их поиск. И если поиск отсортированных элементов в CArrayObj достаточно быстрая операция, то вот со вставкой настоящая беда. Т.к. быстрый поиск требует упорядоченности, то от можественных вставок не избавиться, а это существенно замедлит производительность.
Я извиняюсь!
Я только разбираюсь со списками и созданием объектов.
Когда я начал тестировать и копаться в вашем коде нашел ошибку незначительную, но могу и ошибаться.
замер скорости в сравнении библиотек вашей и стандартной кто быстрей вы в описание говорите про одно, а на графике показываете другое. Это вы не заметили или я неправильно читаю график.??
П.П. 4.3
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Опубликована статья Рецепты MQL5 - Реализуем ассоциативный массив или словарь для быстрого доступа к данным:
Эта статья описывает удобный класс для хранения информации - ассоциативный массив или словарь. Благодаря этому классу можно получать доступ к информации по ее ключу.
Ассоциативный массив напоминает обычный массив, однако вместо индекса он использует некий уникальный ключ, например, перечисление ENUM_TIMEFRAMES или какой-либо текст. Что конкретно является ключом - не важно, важно чтобы этот ключ был уникальным. Благодаря такому алгоритму хранения данных многие аспекты программирования значительно упрощаются.
Например, функция, которая бы принимала код ошибки и печатала текстовой эквивалент этой ошибки, могла бы выглядеть так:
Позже мы разберем специфику данного кода.
Прежде чем подойти к непосредственному описанию внутренней логики ассоциативного массива, мы подробно рассмотрим два основных способа хранения данных - массивы и списки. Наш словарь будет базироваться именно на основе этих двух типах данных, поэтому специфику их работы необходимо хорошо представлять. Описанию типов данных посвящена глава 1. Вторая глава посвящена описанию ассоциативного массива и способа работы с ним.
Автор: Vasiliy Sokolov