FindMapElement

Anfängerfragen zum Programmieren mit PureBasic.
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

FindMapElement

Beitrag von Martin66119 »

Guten Tag,

da ich nur 1x im Jahr eine Minianwednung erstelle (brauche auch nichts großes), komme ich eigentlich nicht viel weiter in meinem Wissen. Vor einigen Monaten hatte ich mal die Frage wie kann man in zwei Listen oder Felder möglichst schnell die Unterschiede herausfinden, gestellt. Die Vorschläge habe ich leider nicht ganz verstanden. Deshalb habe ich folgendes gemacht.

Code: Alles auswählen

  

NewList Liste1.s()
NewMap Datei1.s()
NewMap Datei2.s()
  
While NextElement(Liste1())                
      Ergebnis = FindMapElement(Datei2(),Liste1()) 
      If Ergebnis <> 0 
            DeleteMapElement(Datei2(), Liste1())
            FindMapElement(Datei1(),Liste1()) 
            DeleteMapElement(Datei1(), Liste1()) 
        EndIf                             
Wend
Wenn die Schleife durch ist, sind nur noch die Unterschiede in Datei1() und Datei2() enthalten.

Nun Frage ich mich aber wenn in der Datei2() ein Element 2x vorhanden ist und das gleich 1x in der Liste1() werden die beiden dann duch den DeleteMapElement(Datei2(), Liste1()) in Dastei2() gelöscht?

Grüße
Martin
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: FindMapElement

Beitrag von STARGÅTE »

Nach diesen Testergebnis nicht:

Code: Alles auswählen

NewMap Test.i()

AddMapElement(Test(), "A", #PB_Map_NoElementCheck)
Test() = 1
AddMapElement(Test(), "B", #PB_Map_NoElementCheck)
Test() = 2
AddMapElement(Test(), "A", #PB_Map_NoElementCheck)
Test() = 3

ForEach Test()
	Debug "Test["+MapKey(Test())+"] = "+Str(Test())
Next

DeleteMapElement(Test(), "A")

Debug "---"
ForEach Test()
	Debug "Test["+MapKey(Test())+"] = "+Str(Test())
Next
Durch DeleteMapElement() wird immer nur genau ein Element gelöscht, wenn der Key mehrfach besetzt ist, dann wird nur das zuletzt hinzugefügte gelöscht.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Nun habe ich in der Liste1() folgende Elemente
2,3,4
In der Map Datei1() sind auch die Elemente
2,3,4

und der Map Datei2() die Elemente
4,1,2,3,4,5

Wenn die Schleife durch ist, ist der Unterschied 1 und 5

Code: Alles auswählen

   While NextElement(Liste1())                
                Ergebnis = FindMapElement(Datei2(),Liste1()) 
                If Ergebnis <> 0 
                  DeleteMapElement(Datei2(), Liste1())
                  FindMapElement(Datei1(),Liste1()) 
                  DeleteMapElement(Datei1(), Liste1()) 
                EndIf                             
             Wend
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Nun hab ichs. Ich muss halt nur die Hilfe richtig lesen. Das richtige Flag bei AddElement und schon ist die 4 da

AddMapElement(Datei1(),Zeile,#PB_Map_NoElementCheck)

Gruß un d Danke für die Hilfe
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Sorry noch eine Frage hinterher.

Hat jemand ggf. einen verwendbaren Code, der schneller ist wie FindMapElement und Delete MapElement.

Grüße
matbal
Beiträge: 261
Registriert: 30.03.2011 20:53

Re: FindMapElement

Beitrag von matbal »

Vielleicht reicht es ja schon, die Map mit mehr Slots zu erstellen. Am schnellsten ist eine Map, wenn sie so viele Slots enthält, wie Elemente hinzugefügt werden sollen.

Code: Alles auswählen

NewMap Datei.s(10000)
Die Anzahl der Slots ist immer ein Kompromiß zwischen Speicherverbrauch und Geschwindigkeit.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: FindMapElement

Beitrag von STARGÅTE »

Martin66119 hat geschrieben:Hat jemand ggf. einen verwendbaren Code, der schneller ist wie FindMapElement und Delete MapElement.
Soweit ich mich erinnere, wurde dir ja damals bereichs ein Code gegeben, einfach noch mal ansehen.

Außerdem: "schneller" als was? Wie hast du die Zeit gemessen? Um welche Zeiten geht es?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Habe nun bei NewMap Datei1() in die Klammer 20000 eingetragen. Und schon braucht das Programm nur noch 61 ms statt 121 ms.

Danke
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Der Vergleich besteht aus 11000 x 11000 Zeichenketten. Jeder String ist ca 80 Zeichen lang. In der Liste 1 ist ein String enthalten der in der Liste 2 nicht enthalten ist. In der Liste 2 sind 2 String entahlten, die in Liste 1 nicht sind.

Gemessen mit elapesdMillisecond
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: FindMapElement

Beitrag von NicTheQuick »

Wenn du tatsächlich nur Listen mit Zahlen oder eindeutig sortierbaren Werten hast, dann geht das ganze auch deutlich schneller, indem man beide Listen sortiert und dann nacheinander durch geht.

Code: Alles auswählen

EnableExplicit

Procedure diff(List list1.s(), List list2.s())
	
	SortList(list1(), #PB_Sort_Ascending)
	SortList(list2(), #PB_Sort_Ascending)
	
	Protected NewList *onlyIn1.String()
	Protected NewList *onlyIn2.String()
	
	FirstElement(list1())
	FirstElement(list2())
	
	Protected next1.i, next2.i
	
	Repeat
		; Nur, damit man sieht, was gerade verglichen wird
		Debug "Vergleiche '" + list1() + "' - '" + list2() + "'"
		
		next1 = #True
		next2 = #True
		If (list1() = list2())
			; Element ist in beiden Listen, also tue nichts
		ElseIf (list1() < list2())
			; Element in Liste 1 ist nicht in Liste 2
			If AddElement(*onlyIn1())
				*onlyIn1() = @list1()
			EndIf
			next2 = #False
		Else
			; Element in Liste 2 ist nicht in Liste 1
			If AddElement(*onlyIn2())
				*onlyIn2() = @list2()
			EndIf
			next1 = #False
		EndIf
		
		If (next1)
			If (Not NextElement(list1()))
				; Wenn es in Liste 1 nicht mehr weiter geht
				While NextElement(list2())
					If AddElement(*onlyIn2())
						*onlyIn2() = @list2()
					EndIf
				Wend
				Break
			EndIf
		EndIf
		If (next2)
			If (Not NextElement(list2()))
				; Wenn es in Liste 2 nicht mehr weiter geht
				While NextElement(list1())
					If AddElement(*onlyIn1())
						*onlyIn1() = @list1()
					EndIf
				Wend
				Break
			EndIf
		EndIf
	ForEver
	
	Debug ""
	Debug "Zeilen, die nur in Liste 1 vorhanden sind:"
	ForEach *onlyIn1()
		Debug "'" + *onlyIn1()\s + "'"
	Next
	Debug ""
	
	Debug "Zeilen, die nur in Liste 2 vorhanden sind:"
	ForEach *onlyIn2()
		Debug "'" + *onlyIn2()\s + "'"
	Next
	Debug ""
EndProcedure

NewList liste1.s()
NewList liste2.s()
Define zeile.s

Restore Datei1
Repeat
	Read.s zeile
	If (AddElement(liste1()))
		liste1() = zeile
		
	EndIf
Until zeile = ""

Restore Datei2
Repeat
	Read.s zeile
	If (AddElement(liste2()))
		liste2() = zeile
	EndIf
Until zeile = ""

diff(liste1(), liste2())

DataSection
	Datei1:
		Data.s "Hallo", "das", "ist", "ein", "Test", "!", ""
	Datei2:
		Data.s "Aber", "Hallo", ",", "das", "Forum", "ist", "ja", "erste", "Sahne", "!", ""
EndDataSection
Achja, und wenn man Geschwindigkeiten messen will, macht man das natürlich ohne Debugger.
Antworten