Generische Klassenbibliothek - Bugs, Beschreibung, Fragen, Nutzungsmöglichkeiten und Vorschläge - Seite 22

 
Alexey Navoykov:

Offenbar meinen Sie nicht Vererbung, sondern einen Wrapper von einer Klasse über eine Struktur?

richtig.
 
//+------------------------------------------------------------------+
//| Determines whether a set contains the specified element.         |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Contains(T item)
  {
//--- check buckets
   if(ArraySize(m_buckets)!=0)
     {
      //--- get hash code for item      
      int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF;
      //--- search item in the slots       
      for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next)
         if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item))
            return(true);
     }
   return(false);
  }

Warum ist das Vorzeichen abgeschnitten?

 
fxsaber:

Warum ist das Vorzeichen abgeschnitten?

der Hash muss positiv sein, da er als Index in der Matrix dient

 
TheXpert:

der Hash muss positiv sein, da er als Index in der Matrix dient

uint?

 
fxsaber:

uint?

macht keinen Sinn

Документация по MQL5: Операции с массивами / ArraySize
Документация по MQL5: Операции с массивами / ArraySize
  • www.mql5.com
"Нулевое измерение = Размер массива / (Первое измерение * Второе измерение * Третье измерение)"
 
TheXpert:

macht keinen Sinn

Die Kombination der hervorgehobenen Zeilen scheint falsch zu sein

Forum zum Thema Handel, automatische Handelssysteme und Testen von Handelsstrategien

Generische Klassenbibliothek - Bugs, Beschreibung, Probleme, Anwendungsfälle und Vorschläge

fxsaber, 2018.06.11 20:04

//+------------------------------------------------------------------+
//| Determines whether a set contains the specified element.         |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Contains(T item)
  {
//--- check buckets
   if(ArraySize(m_buckets)!=0)
     {
      //--- get hash code for item      
      int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF;
      //--- search item in the slots       
      for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next)
         if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item))
            return(true);
     }
   return(false);
  }

Wie kann man ein getrimmtes Haschisch mit einem ungeschnittenen Haschisch vergleichen?

 
fxsaber:

Wie kann man ein getrimmtes Haschisch mit einem ungeschnittenen Haschisch vergleichen?

Ich glaube, sie sind alle abgeschnitten, obwohl ich gleich sagen sollte, dass ich mir den Code nur kurz und vor langer Zeit angesehen habe, ich könnte also falsch liegen.

Sehen Sie sich den Code an, um das Element hinzuzufügen.

 
TheXpert:

Ich glaube, sie sind alle beschnitten, obwohl ich gleich sagen sollte, dass ich den Code erst vor kurzem gesehen habe, ich könnte mich also irren.

Sehen Sie sich den Code an, um ein Element hinzuzufügen.

//+------------------------------------------------------------------+
//| Insert the value with the specified key from the map.            |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Insert(TKey key,TValue value,const bool add)
  {
   if(m_capacity==0)
      Initialize(0);
//--- get hash code from key
   int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF;
   int target_bucket=hash_code%m_capacity;
//--- collisions count in one bucket with different hashes
   int collision_count=0;
//--- search pair with specified key
   for(int i=m_buckets[target_bucket]; i>=0; i=m_entries[i].next)
     {
      //--- hash compare      
      if(m_entries[i].hash_code!=hash_code)
        {
         collision_count++;
         continue;
        }
      //--- value compare     
      if(m_comparer.Equals(m_entries[i].key,key))
        {
         //--- adding duplicate
         if(add)
            return(false);
         m_entries[i].value=value;
         return(true);
        }
     }
//--- check collision
   if(collision_count>=m_collision_threshold)
     {
      int new_size=CPrimeGenerator::ExpandPrime(m_count);
      Resize(new_size);
     }
//--- calculate index
   int index;
   if(m_free_count>0)
     {
      index=m_free_list;
      m_free_list=m_entries[index].next;
      m_free_count--;
     }
   else
     {
      if(m_count==ArraySize(m_entries))
        {
         int new_size=CPrimeGenerator::ExpandPrime(m_count);
         Resize(new_size);
         target_bucket=hash_code%new_size;
        }
      index=m_count;
      m_count++;
     }
//--- set pair
   m_entries[index].hash_code=hash_code;
   m_entries[index].next=m_buckets[target_bucket];
   m_entries[index].key=key;
   m_entries[index].value=value;
   m_buckets[target_bucket]=index;
   return(true);
  }

Ja, danke, es gibt nur keine, die nicht im Code beschnitten sind. Seltsam, dass sie das Trimmen nicht in der HashCode-Methode selbst vorgenommen haben. Offensichtlich diente die Berechnung der Narrensicherheit (krumme benutzerdefinierte Hashes).

 

Es tut mir leid, wenn dies bereits geschehen ist. Ich konnte es in der Dokumentation nicht finden.

Gibt es eine Schleife für Setups? iterator?

 
Viktor Lubimov:

Es tut mir leid, wenn dies bereits geschehen ist. Ich konnte es in der Dokumentation nicht finden.

Gibt es eine Schleife zu den Setups?

Leider nein.
Aber Sie können es selbst umsetzen.
Siehe zum Beispiel das Beispiel aus dem ArtikelMQL5 RECEIPTS - REALIZE ASSOCIATED MASSIVE OR WORLD DATABASE FOR FAST DATA ACCESS

void ReverseEnumerateAll(CList& list)
{
   CObject* node = list.GetLastNode();
   for(int i = list.Total()-1; node != NULL; i--, node = node.Prev())
      printf("Element at " + (string)i); 
}
Как работает этот код? На самом деле все просто. В функции EnumerateAll() в самом начале мы получаем ссылку на первый узел. Затем в цикле for мы печатаем порядковый узел этого узла 
и переходим к следующему узлу командой node = node.Next(), не забывая при этом проитерировать текущий индекс элемента на единицу (i++). Перебор продолжается до тех пор, пока текущий 
узел node не станет равен NULL, за это ответствен код во втором блоке for: node != NULL.

Аналогично работает реверсивная версия этой функции ReverseEnumerateAll() с той лишь разницей, что она вначале получает последний элемент списка CObject* node = list.GetLastNode(). 
В цикле for она получает не следующий, а предыдущий элемент списка node = node.Prev().