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
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..
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?
