Discussão do artigo "Guia Prático MQL5: Implementando um Array Associativo ou um Dicionário para Acesso Rápido ao Dados"
Artigo publicado MQL5 Recipes - Implementar uma matriz associativa ou dicionário para acesso rápido aos dados:
Autor: Vasiliy Sokolov
Trabalho legal, parabéns ao autor! Isso é algo que o MQ deveria ter incluído em \MQL5\Include\Arrays há muito tempo, espero que seja incluído na biblioteca nas próximas versões. A propósito, tudo funciona bem no MQL4 também, aqui estão as medidas do primeiro teste. Entendo que é impossível incluir tipos de dados simples em vez de *CObject devido à falta de ponteiros completos? Ou há alguma maneira de contornar isso?
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
Excelente trabalho, parabéns ao autor! Isso é algo que a MQ deveria ter incluído no MQL5/Include/ Arrays há muito tempo, espero que seja incluído na biblioteca nas próximas versões. A propósito, tudo funciona bem no MQL4 também, aqui estão as medidas do primeiro teste. Entendo que é impossível incluir tipos de dados simples em vez de *CObject devido à falta de ponteiros completos? Ou há alguma maneira de fazer isso funcionar?
Funcionará. Com a ajuda do mecanismo de boxing/unboxing e dos modelos. A ideia é que cada tipo de base seja empacotado em um contêiner KeyValuePairBase. A desembalagem e o retorno do tipo correspondente são feitos por funções internas do tipo GetObjectByKey:
template<typename Type, typename T>
Type GetObjectByKey(T key);É importante enfatizar que trabalhar com tipos de base não trará nenhuma vantagem de desempenho, mas será muito mais conveniente.
Agora tentei criar um CDictionaryBase armazenando um dos tipos básicos de MQL em vez de CObject com base em modelos. Infelizmente, isso não funcionou, pois as funções não permitem retornar um tipo de modelo. É uma pena:
//+------------------------------------------------------------------+ //|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> //+------------------------------------------------------------------+ //| Função de início do programa de script| //+------------------------------------------------------------------+ 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 ...
//+------------------------------------------------------------------+ //| Retorna o objeto por chave.| //+------------------------------------------------------------------+ template<typename T, typename C> C CDictionaryBase::GetValueByKey(T key) { if(!ContainsKey(key)) return NULL; return m_current_kvp.GetValue(); }
Muito ruim.
Portanto, para cada tipo de base, teremos que criar um contêiner de base, ou apenas criar contêineres de tipos de base: CDouble, CLong, CInt, etc.
Agora tentei criar um CDictionaryBase armazenando um dos tipos básicos de MQL em vez de CObject com base em modelos. Infelizmente, não consegui fazer isso, pois as funções não permitem retornar um tipo de modelo.
Elas permitem. Mas o tipo do valor retornado não pode ser deduzido automaticamente, o que, na verdade, é escrito pelo compilador.
Você pode usar uma pequena muleta na forma de um pseudoparâmetro.
template<typename T, typename C> C CDictionaryBase::GetValueByKey(T key, C) { if(!ContainsKey(key)) return NULL; return m_current_kvp.GetValue(); }
Eles fazem isso. Mas o tipo do valor retornado não pode ser deduzido automaticamente, que é o que o compilador de fato escreve.
Você pode usar uma pequena muleta na forma de um pseudoparâmetro.
Onde está a muleta de fato?
Um segundo parâmetro foi adicionado
Você já tentou comparar o desempenho? A partir de que tamanho de dados começa a vantagem sobre a pesquisa binária em um array de strings classificadas?
Não fiz testes exatos, mas, de acordo com minhas observações, a vantagem de velocidade começa a aparecer a partir de dezenas de milhares de elementos. Ou seja, em tarefas cotidianas com 100 a 10.000 elementos, não é possível obter um ganho de desempenho.
Outro aspecto importante aqui é a conveniência de trabalhar com o contêiner. Você não precisa escrever métodos adicionais para pesquisar elementos. Muitas tarefas cotidianas com dicionários tornam-se muito mais fáceis de implementar. Você não precisa criar um elemento para pesquisar um índice e, em seguida, recuperar o elemento necessário pelo índice correspondente, etc., etc.
Embora aqui eu tenha pensado que o desempenho deveria ser medido como o tempo total para inserir elementos e pesquisá-los. E se a pesquisa de itens classificados em CArrayObj é uma operação bastante rápida, então a inserção é um verdadeiro problema. Como a pesquisa rápida exige ordem, não podemos nos livrar de possíveis inserções, e isso reduzirá significativamente o desempenho.
Muito interessante e está claro que o dicionário é um organizador de dados muito útil e fácil de usar.
Obrigado por seu compartilhamento.
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Novo artigo Guia Prático MQL5: Implementando um Array Associativo ou um Dicionário para Acesso Rápido ao Dados foi publicado:
Este artigo descreve um algoritmo especial que permite ter acesso aos elementos através de suas chaves únicas. Qualquer tipo de dados de base pode ser usado como uma chave. Por exemplo, ele pode ser representado como uma variável do tipo string ou inteiro. Tais contentores de dados são comumente referenciados a um dicionário ou um array associativo. Ele fornece uma maneira mais fácil e eficiente na resolução de problemas.
Este artigo descreve uma classe para facilitar o armazenamento de informações, ou seja, um array associativo ou em um dicionário. Esta classe permite obter acesso a informações por sua chave.
O array associativo se assemelha a um array regular. Mas em vez de um índice, ele utiliza alguma chave única, por exemplo, a enumeração ENUM_TIMEFRAMES ou algum texto. Não importa o que a chave representa. A unicidade da chave que importa. Este algoritmo de armazenamento de dados simplifica significativamente muitos aspectos da programação.
Por exemplo, uma função, que daria um código de erro e imprime um texto equivalente ao erro, poderia ser o seguinte:
Nós vamos olhar para as características específicas deste código mais tarde.
Antes de tratar diretamente uma descrição da lógica interna do array associativo, nós vamos considerar os detalhes dos dois métodos principais de armazenamento de dados, ou seja, arrays e listas. Nosso dicionário será com base nesses dois tipos de dados, é por isso que se deve ter uma boa compreensão de suas características específicas. O capítulo 1 é dedicado à descrição dos tipos de dados. O segundo capítulo é dedicado à descrição do array associativo e os métodos de trabalhar com ele.
Autor: Vasiliy Sokolov