Seite 1 von 3

Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 08:46
von techniker
Hallo zusammen,

eine kurze (und ggf. dumme) Frage:
Wenn ich eine Map mehrmals mit ForEach abarbeite, ist dann die Reihenfolge der Elemente immer gleich?

Danke! :)

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 09:29
von TroaX
Moin,

generell schon. Es gibt keinen rationalen Grund, warum die Map jedes mal gewürfelt werden sollte. Eine zufällige (zumindest zufällig wirkende) Reihenfolge müsste ja durch etwas forciert werden. ForEach fängt immer beim ersten Element an und läuft, wenn nicht durch eine Abbruchbedingung unterbrochen, bis zum letzten Element durch. Und die Reihenfolge bleibt dabei unberührt. Das würde sonst dem System mehr Rechenzeit unnötig abverlangen, als es muss. Schließlich sind die ja im Speicher auch in der Reihenfolge hinterlegt, wie die Elemente angelegt wurden ;)

Code: Alles auswählen

EnableExplicit

OpenConsole()

NewMap MultipleRunner.s()
Define.i Counter

MultipleRunner("Test_1") = "Test_1"
MultipleRunner("Test_2") = "Test_2"
MultipleRunner("Test_3") = "Test_3"
MultipleRunner("Test_4") = "Test_4"
MultipleRunner("Test_5") = "Test_5"
MultipleRunner("Test_6") = "Test_6"
MultipleRunner("Test_7") = "Test_7"
MultipleRunner("Test_8") = "Test_8"
MultipleRunner("Test_9") = "Test_9"

For Counter = 1 To 10
  ForEach MultipleRunner()
    PrintN(MapKey(MultipleRunner()) + " " + MultipleRunner())
    If MultipleRunner() = "Test_6" And Mod(Counter, 2) = 0
      Break
    EndIf
  Next
  PrintN("")
Next

Input()
Output:

Code: Alles auswählen

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6
Test_7 Test_7
Test_8 Test_8
Test_9 Test_9

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6
Test_7 Test_7
Test_8 Test_8
Test_9 Test_9

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6
Test_7 Test_7
Test_8 Test_8
Test_9 Test_9

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6
Test_7 Test_7
Test_8 Test_8
Test_9 Test_9

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6
Test_7 Test_7
Test_8 Test_8
Test_9 Test_9

Test_1 Test_1
Test_2 Test_2
Test_3 Test_3
Test_4 Test_4
Test_5 Test_5
Test_6 Test_6

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 09:47
von techniker
Das Ergebnis hatte ich auch - aber ich weiß nicht, ob das immer so ist.
99,5% von meinem Programm nutzt die Map am effektivsten durch das FindMapElement().
Es gibt aber einen Punkt, bei dem ich die Einmaligkeit der Element-Werte prüfen muss..

Das ist dann eine verschachtelte ForEach() auf die gleiche Map.
Wenn die Reihenfolge immer gleich ist, könnte ich die untere ForEach() mit einem anderen
Offset starten und somit wird die Funktion schneller..

(Schwierig zu erklären..)

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 10:08
von STARGÅTE
techniker hat geschrieben: 20.01.2023 08:46 Wenn ich eine Map mehrmals mit ForEach abarbeite, ist dann die Reihenfolge der Elemente immer gleich?
Das ist keine zwingende Bedingung bei Maps. Bei einer Linked List sind die Elemente, wie es der Name schon sagt verknüpft und jedes Element kennt seinen Vorgänger und seinen Nachfolger. Map-Elemente sind nicht verknüpft.
Es wäre jedoch durchaus plausibel, wenn sich die Reihenfolge zumindest nicht ändert, solange kein Element hinzugefügt oder entfernt wird. Eine Garantie gibt es dafür aber nicht.
Außerdem muss es nicht einmal sein, dass die Reihenfolge von PB-Version zu PB-Version erhalten bleibt, wenn sich etwas am Hash-Algorithmus der Map ändert.
TroaX hat geschrieben: 20.01.2023 09:29 Schließlich sind die ja im Speicher auch in der Reihenfolge hinterlegt, wie die Elemente angelegt wurden
Nein das stimmt nicht. In deinem Beispiel sieht das so aus, weil die Keys eine gewisse Reihenfolge haben. Im allgemeinen, werden die Elemente aber nicht so durchlaufen, wie sie angelegt wurden.

Code: Alles auswählen

Define NewMap Example.s()

Example("Some String") = "1"
Example("Another String") = "2"
Example("Any String") = "3"
Example("An additional String") = "4"

ForEach Example()
	Debug "Example(" + MapKey(Example()) + ") = " + Example()
Next

Debug "---"

Example("A new String") = "5"

ForEach Example()
	Debug "Example(" + MapKey(Example()) + ") = " + Example()
Next
Edit:
techniker hat geschrieben: 20.01.2023 09:47 Es gibt aber einen Punkt, bei dem ich die Einmaligkeit der Element-Werte prüfen muss..

Das ist dann eine verschachtelte ForEach() auf die gleiche Map.
Wenn die Reihenfolge immer gleich ist, könnte ich die untere ForEach() mit einem anderen
Offset starten und somit wird die Funktion schneller..

(Schwierig zu erklären..)
Dafür gibt es ein Beispiel in der Hilfe:
https://www.purebasic.com/german/docume ... ition.html

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 12:39
von mk-soft
Man verwendet ja Maps um nicht durchsuchen zu müssen und ist somit schon sehr schnell.

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 12:57
von Lord
Hi!

Wenn ich eine Map nutze und wissen muß, ob ein Element mehrfach vorkommt,
nutze ich eine Struktur. ein Element der Struktur ist dann ein Counter, welcher
bei dem Hinzufügen eines Elements um ein erhöht wird.
Bei der Abfrage des Elements wird diese Counter dann auf einen Wert größer
als eins geprüft.

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 13:32
von TroaX
STARGÅTE hat geschrieben: 20.01.2023 10:08 Nein das stimmt nicht. In deinem Beispiel sieht das so aus, weil die Keys eine gewisse Reihenfolge haben. Im allgemeinen, werden die Elemente aber nicht so durchlaufen, wie sie angelegt wurden.
Hmm ich habe den PureBasic-Compiler für ziemlich primitiv gehalten. Das überrascht mich jetzt. Erklärt zwar nicht, warum das so ist. Aber wenn dem so ist, ziehe ich meine Aussage zurück. Für so etwas habe ich Maps sowieso nicht genutzt. Siehe mk-soft :lol:
Man verwendet ja Maps um nicht durchsuchen zu müssen und ist somit schon sehr schnell.

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 13:42
von techniker
mk-soft hat geschrieben: 20.01.2023 12:39 Man verwendet ja Maps um nicht durchsuchen zu müssen und ist somit schon sehr schnell.
Wie erkennst du sonst, welche Keys von Dubletten betroffen sind?
(Dubletten sollen nicht verboten sein, aber müssen detektiert werden)
Die Map hat momentan bis zu 70'000 Elemente.

obst("key1") = "Apfel"
obst("Key2") = "Birne"
obst("key3") = "Banane"
obst("key4") = "Birne"
obst("key5") = "Weintraube"
obst("key6") = "Banane"
obst("key7") = "Banane"

Bei diesem Beispiel brauche ich folgende Keys als Ergebnis:
key2, key3, key4, key6, key7

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 13:56
von mk-soft
Map Keys müssen eindeutig sein. Sonst ist der schnelles zugriff nicht möglich. Man kann zwar mehrere Keys mit gleichen Namen anlegen. Es ist aber immer nur der letzte zu greifbar bis diese gelöscht wird (siehe PB-Help AddMapElemenet)

Für ähnliche fälle verwende ich ein Zusammenspiel für LinkedList für die Daten und Maps für Index verweise.

Code: Alles auswählen


Structure udtMyData
  Name.s
  Value.i
EndStructure

Global NewList MyData.udtMyData()
Global NewMap *IndexMyData.udtMyData()

; Dummy Data

For i = 1 To 100
  AddElement(MyData())
  MyData()\Name = "Name_" + i
  MyData()\Value = Random(1000)
Next

; Build Index
ForEach MyData()
  *IndexMyData(MyData()\Name) = @MyData()
Next

If FindMapElement(*IndexMyData(), "Name_1")
  Debug *IndexMyData()\Value
EndIf

If FindMapElement(*IndexMyData(), "Name_50")
  Debug *IndexMyData()\Value
EndIf

Re: Durchlauf von Map mit ForEach

Verfasst: 20.01.2023 14:02
von techniker
mk-soft hat geschrieben: 20.01.2023 13:56 Map Keys müssen eindeutig sein. Sonst ist der schnelles zugriff nicht möglich.
Das ist mir schon klar - darum nutze ich ja auch Maps.. :mrgreen:
Wie gesagt: 99,5% von der Software nutzen Maps genau wegen dem schnellen Zugriff.

Es gibt aber EINE Funktion, welche Dubletten erkennen muss.
Und wie soll ich die enthaltenen Werte sonst prüfen, als sequentielles abarbeiten? :)