Discussione sull’articolo "MQL5 Cookbook: Implementazione di un array associativo o di un dizionario per l'accesso rapido ai dati"
Articolo pubblicato Ricette MQL5 - Implementare un array associativo o un dizionario per accedere rapidamente ai dati:
Autore: Vasiliy Sokolov
Ottimo lavoro, complimenti all'autore! Questo è qualcosa che MQ avrebbe dovuto includere in \MQL5\Include\Arrays molto tempo fa, spero che venga incluso nella libreria nelle prossime versioni. A proposito, tutto funziona bene anche in MQL4, ecco le misure del primo test. Ho capito che è impossibile includere tipi di dati semplici al posto di *CObject a causa della mancanza di puntatori completi? Oppure c'è un modo per aggirare il problema?
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
Ottimo lavoro, complimenti all'autore! Questo è qualcosa che MQ avrebbe dovuto includere in MQL5/Include/ Arrays molto tempo fa, spero che venga incluso nella libreria nelle prossime versioni. A proposito, tutto funziona bene anche in MQL4, ecco le misure del primo test. Ho capito che è impossibile includere tipi di dati semplici al posto di *CObject a causa della mancanza di puntatori completi? Oppure c'è un modo per farlo funzionare?
Funzionerà. Con l'aiuto del meccanismo di boxing/unboxing e dei template. L'idea è che ogni tipo di base sia impacchettato in un contenitore KeyValuePairBase. Lo spacchettamento e la restituzione del tipo corrispondente avviene tramite funzioni interne del tipo GetObjectByKey:
template<typename Type, typename T>
Type GetObjectByKey(T key);È importante sottolineare che lavorare con i tipi di base non darà alcun vantaggio in termini di prestazioni, ma sarà molto più comodo.
Ora ho provato a creare un CDictionaryBase che memorizza uno dei tipi di base di MQL invece di CObject sulla base di modelli. Purtroppo non ha funzionato, le funzioni non consentono di restituire un tipo di modello. È un peccato:
//+------------------------------------------------------------------+ //|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> //+------------------------------------------------------------------+ //| Funzione di avvio del programma di 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 ...
//+------------------------------------------------------------------+ //| Restituisce l'oggetto per chiave.| //+------------------------------------------------------------------+ template<typename T, typename C> C CDictionaryBase::GetValueByKey(T key) { if(!ContainsKey(key)) return NULL; return m_current_kvp.GetValue(); }
Peccato.
Quindi, per ogni tipo di base dovremo creare un contenitore di base, o semplicemente creare contenitori di tipi di base: CDouble, CLong, CInt, ecc.
Ora ho provato a creare un CDictionaryBase che memorizzi uno dei tipi di base di MQL invece di CObject sulla base di modelli. Purtroppo non ci sono riuscito, le funzioni non consentono di restituire un tipo di modello.
Lo fanno. Ma non è possibile dedurre automaticamente il tipo del valore restituito, che viene effettivamente scritto dal compilatore.
È possibile utilizzare una piccola stampella sotto forma di pseudo-parametro.
template<typename T, typename C> C CDictionaryBase::GetValueByKey(T key, C) { if(!ContainsKey(key)) return NULL; return m_current_kvp.GetValue(); }
Lo fanno. Ma non è possibile dedurre automaticamente il tipo del valore restituito, che è quello che il compilatore scrive effettivamente.
Si può usare una piccola stampella sotto forma di pseudo-parametro.
Dov'è la stampella vera e propria?
È stato aggiunto un secondo parametro
Avete provato a confrontare le prestazioni. A quale dimensione dei dati inizia il vantaggio rispetto alla ricerca binaria in un array di stringhe ordinate?
Non ho fatto test precisi, ma secondo le mie osservazioni il vantaggio in termini di velocità inizia a manifestarsi a partire da decine di migliaia di elementi. In altre parole, nelle attività quotidiane con 100-10.000 elementi non è possibile ottenere un guadagno in termini di prestazioni.
Un altro aspetto importante è la comodità di lavorare con il contenitore. Non è necessario scrivere metodi aggiuntivi per cercare gli elementi. Molte operazioni quotidiane con i dizionari diventano molto più semplici da implementare. Non è necessario creare un elemento per cercare un indice, poi recuperare quello necessario in base all'indice corrispondente, ecc.
s.s. Tuttavia, pensavo che le prestazioni dovessero essere misurate come il tempo totale per l'inserimento di elementi e la loro ricerca. E se la ricerca di elementi ordinati in CArrayObj è un'operazione abbastanza veloce, allora l'inserimento è un vero problema. Poiché la ricerca veloce richiede ordine, non possiamo sbarazzarci dei possibili inserimenti e questo rallenterà significativamente le prestazioni.
È molto interessante ed è chiaro che il dizionario è un organizzatore di dati molto utile e facile da usare.
Grazie per la condivisione.
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso
Il nuovo articolo MQL5 Cookbook: Implementazione di un array associativo o di un dizionario per l'accesso rapido ai dati è stato pubblicato:
Questo articolo descrive uno speciale algoritmo che consente di accedere agli elementi tramite le loro chiavi univoche. Qualsiasi tipo di dati di base può essere utilizzato come chiave. Ad esempio può essere rappresentato come una stringa o una variabile intera. Tale contenitore di dati è comunemente indicato come dizionario o array associativo. Fornisce un modo più semplice ed efficiente di risolvere i problemi.
Un array con elementi di tipo arbitrario soffre di un solo grande difetto: ci vuole molto tempo e fatica se si vuole inserire un nuovo elemento, specialmente se questo elemento deve essere inserito al centro dell'array. Gli elementi si trovano in una sequenza, quindi per l'inserimento è necessario ridimensionare l'array per aumentare di uno il numero totale di elementi e quindi riorganizzare tutti gli elementi che seguono l'oggetto inserito in modo che i loro indici corrispondano ai loro nuovi valori.
Supponiamo di avere un array composto da 7 elementi e di voler inserire un altro elemento in quarta posizione. Uno schema di inserimento approssimativo sarà il seguente:
Fig. 2. Ridimensionamento dell'array e inserimento di un nuovo elemento
Autore: Vasiliy Sokolov