Seite 1 von 1
ForEach bei Maps = verkehrte Reihenfolge?
Verfasst: 15.03.2024 22:44
von Delle
Mal eine Frage: wieso "sortiert" hier PB eigenmächtig, wenn man für den Key eine Zahl nimmt?
Habe mit Zahlen 100 - 125 fortlaufend (!) die Map gefüllt, Ausgabe mit ForEach ist dann nicht Start mit 100, sondern mit 120-125, danach beginnt er ab 100 hochzuzählen...
Gibt's eine Logik dahinter?
Re: ForEach bei Maps = verkehrte Reihenfolge?
Verfasst: 15.03.2024 23:01
von mk-soft
Es sind ja auch keine Zahlen, sondern Strings. Auch bei Zahlen werden diese nicht die gleiche Reihenfolge haben.
Maps sind immer unsortiert, da diese asl Hashtabelle abgelegt werden ...
Link:
https://de.wikipedia.org/wiki/Hashtabelle
Re: ForEach bei Maps = verkehrte Reihenfolge?
Verfasst: 15.03.2024 23:02
von Kiffi
Auszug aus der PB-Hilfe hat geschrieben:Die Einfüge-Reihenfolge der Elemente wird beim Verwenden einer Map nicht gespeichert (anders als bei einer verknüpften Liste) und daher kann sie auch nicht sortiert werden.
Re: ForEach bei Maps = verkehrte Reihenfolge?
Verfasst: 16.03.2024 07:15
von DarkDragon
PB Maps sind als
Hashtabellen implementiert. D.h. das läuft wie folgt:
Im Hintergrund hast du ein Array. Wird auf ein Element mit dem key X zugegriffen wird ein integer hashwert von X berechnet der möglichst kollisionsfrei ist und an der Stelle im Array wird nach dem Element gesucht. Die Reihenfolge wird nicht gewährleistet.
Zugriffszeit auf ein Element wäre damit konstant O(1). Bei einer Linked List wäre es O(n).
Re: ForEach bei Maps = verkehrte Reihenfolge?
Verfasst: 16.03.2024 10:57
von Delle
Mit einem führenden A funktioniert es:
Code: Alles auswählen
Country("A100")= ...
Country("A200")= ...
Country("A300")= ...
Aber gut vielleicht sollte ich das wirklich in LL's packen bzw. gleich in eine Datenbank, wenn dann auch noch weitere Elemente sortiert werden können sollen...
Re: ForEach bei Maps = verkehrte Reihenfolge?
Verfasst: 16.03.2024 15:35
von mk-soft
Du kannst auch eine Kombination von Listen und Maps verwenden.
Die Daten sind in der Liste und der Schnellzugriff über Maps mit Zeiger auf die Daten.
Hier muss aber immer die Liste und Maps sauber gepflegt werden, was aber gut geht.
Du kannst auch die Liste sortieren, da die Zeiger auf die Daten sich dabei nicht ändern.
Einzige Regel ist das der Name eindeutig sein muss. Dieses kann man aber über die Map abfragen ob es den Namen schon gibt
Code: Alles auswählen
Structure udtData
Name.s
Value.i
Random.i
EndStructure
Global NewList myData.udtData()
Global NewMap *myNamedData.udtData()
Debug "Create data ..."
Define i, name.s
For i = 0 To 10000
name = "A" + Str(i)
*pData = AddElement(myData())
myData()\Name = name
myData()\Value = i
myData()\Random = Random(5000, 1000)
*myNamedData(Name) = *pData
Next
Debug "List Data ..."
ForEach myData()
Debug myData()\Name + " Value = " + myData()\Value + " / Random = " + myData()\Random
If myData()\Value > 10
Break
EndIf
Next
Debug "Get data over name ..."
name = "A6"
If FindMapElement(*myNamedData(), name)
Debug myData()\Name + " Value = " + myData()\Value + " / Random = " + myData()\Random
Else
Debug name + " nicht gefunden"
EndIf
name = "A9999"
If FindMapElement(*myNamedData(), name)
Debug myData()\Name + " Value = " + myData()\Value + " / Random = " + myData()\Random
Else
Debug name + " nicht gefunden"
EndIf
name = "A10001"
If FindMapElement(*myNamedData(), name)
Debug myData()\Name + " Value = " + myData()\Value + " / Random = " + myData()\Random
Else
Debug name + " nicht gefunden"
EndIf
Debug "Delete data over index ..."
i = 5001
SelectElement(myData(), i)
Debug "Delete " + myData()\Name
DeleteMapElement(*myNamedData(), myData()\Name)
DeleteElement(myData())
Debug "Delete data over name ..."
name = "A5005"
If FindMapElement(*myNamedData(), name)
Debug "Delete " + name
*pData = *myNamedData()
ChangeCurrentElement(myData(), *pData)
DeleteElement(myData())
DeleteMapElement(*myNamedData())
EndIf
name = "A5005"
If FindMapElement(*myNamedData(), name)
Debug name + "Value = " + *myNamedData()\Value
Else
Debug name + " nicht gefunden"
EndIf
Debug "List Data ..."
SelectElement(myData(), 5000)
i = 1
Repeat
Debug myData()\Name + " Value = " + myData()\Value + " / Random = " + myData()\Random
i + 1
If i > 10
Break
EndIf
Until Not NextElement(myData())
SortStructuredList(myData(), #PB_Sort_Ascending, OffsetOf(udtData\Random), #PB_Integer)
Debug "List Sorted Data ..."
SelectElement(myData(), 5000)
i = 1
Repeat
Debug myData()\Name + " Value = " + myData()\Value + " / Random = " + myData()\Random
i + 1
If i > 10
Break
EndIf
Until Not NextElement(myData())
Debug "Get data over name ..."
name = "A5000"
If FindMapElement(*myNamedData(), name)
Debug name + " Value = " + *myNamedData()\Value
Else
Debug name + " nicht gefunden"
EndIf