Seite 1 von 9

FindMapElement

Verfasst: 19.06.2014 12:54
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

Re: FindMapElement

Verfasst: 19.06.2014 13:05
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.

Re: FindMapElement

Verfasst: 19.06.2014 13:20
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

Re: FindMapElement

Verfasst: 19.06.2014 13:43
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

Re: FindMapElement

Verfasst: 19.06.2014 14:10
von Martin66119
Sorry noch eine Frage hinterher.

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

Grüße

Re: FindMapElement

Verfasst: 19.06.2014 21:31
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.

Re: FindMapElement

Verfasst: 19.06.2014 21:54
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?

Re: FindMapElement

Verfasst: 19.06.2014 22:08
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

Re: FindMapElement

Verfasst: 19.06.2014 22:19
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

Re: FindMapElement

Verfasst: 19.06.2014 22:22
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.