ForEach bei Maps = verkehrte Reihenfolge?

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Delle
Beiträge: 1130
Registriert: 10.05.2005 22:48

ForEach bei Maps = verkehrte Reihenfolge?

Beitrag von Delle »

Mal eine Frage: wieso "sortiert" hier PB eigenmächtig, wenn man für den Key eine Zahl nimmt?

Bild

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?
PB 6.21 | Win 11
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: ForEach bei Maps = verkehrte Reihenfolge?

Beitrag 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
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: ForEach bei Maps = verkehrte Reihenfolge?

Beitrag 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.
a²+b²=mc²
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: ForEach bei Maps = verkehrte Reihenfolge?

Beitrag 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).
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Delle
Beiträge: 1130
Registriert: 10.05.2005 22:48

Re: ForEach bei Maps = verkehrte Reihenfolge?

Beitrag 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...
PB 6.21 | Win 11
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: ForEach bei Maps = verkehrte Reihenfolge?

Beitrag 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

Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten