Seite 2 von 2

Re: NewList

Verfasst: 06.05.2013 23:29
von NicTheQuick
Hast du den Zusatz-String oben nur aus Versehen mit einem extra Leerzeichen vor dem Unterstrich versehen oder war das extra?
Jedenfalls ist das Hauptproblem das 'SelectElement()'. Das arbeitet bei Listen nämlich nicht sonderlich effektiv und sollte bei Listen-Operationen vermieden werden. Wenn man per Index auf etwas zugreifen will, nutzt man Arrays.

Außerdem ist es nicht notwendig in jedem Schleifendurchlauf einmal vorwärts und wieder zurück zu gehen. Eigentlich muss man sich nur den Pointer zum ersten Element merken und dann ab dem zweiten anfangen über die Liste zu iterieren, das aktuelle Element mit dem 'gemerkten Element' vergleichen und dann den Pointer auf das jetzt aktuelle Element setzen, damit im nächsten Schleifendurchlauf damit verglichen wird.

Das ganze sieht dann so aus und dauert bei mir gerade mal 71 ms.

Code: Alles auswählen

NewList File1.s()

Define i.i
For i = 0 To 1000000
	If AddElement(File1())
		File1() = "Dies ist ein Teststring_" + Str(i)
	EndIf
Next

If AddElement(File1())
	File1() = "Dies ist ein Teststring_" + Str(1000000)
EndIf

SortList(File1(), #PB_Sort_Ascending)


Define Time.i = ElapsedMilliseconds()
;---------------------------------------------------------
If FirstElement(File1())
	Define *File1Last.String = @File1()
	While NextElement(File1())
		If *File1Last\s = File1()
			j + 1
		EndIf
		*File1Last.String = @File1()
	Wend
EndIf
;---------------------------------------------------------
Time = ElapsedMilliseconds() - Time

MessageRequester("Info", "Zeit: " + Str(Time) + #CRLF$ + "Doppelt: " + Str(j))
Bei Fragen fragen!

Nachtrag:
Natürlich gehört das Sortieren der Liste normalerweise zur Zeitmessung dazu und sollte deswegen auch berücksichtigt werden. Und um das ganze auch mit praktischen Werten vergleichen zu können, sollte man die Liste zu Anfang auch randomisieren.
Dann dauert es mit folgendem Testcode bei mir 1500 ms:

Code: Alles auswählen

NewList File1.s()

RandomSeed(0)	;Selber Randomseed, damit immer die selben Ergebnisse kommen
Define i.i
For i = 0 To 1000000
	If AddElement(File1())
		File1() = "Dies ist ein Teststring_" + Str(Random(1000000))
	EndIf
Next

Define Time.i = ElapsedMilliseconds()
SortList(File1(), #PB_Sort_Ascending)
;---------------------------------------------------------
If FirstElement(File1())
	Define *File1Last.String = @File1()
	While NextElement(File1())
		If *File1Last\s = File1()
			j + 1
		EndIf
		*File1Last.String = @File1()
	Wend
EndIf
;---------------------------------------------------------
Time = ElapsedMilliseconds() - Time

MessageRequester("Info", "Zeit: " + Str(Time) + #CRLF$ + "Doppelt: " + Str(j))

Re: NewList

Verfasst: 07.05.2013 15:17
von Martin66119
Vielenm Dank NicTheQuick,

leider verstehe ich eine Punkt nicht. Die Frage habe ich hinter die entsprechende Codezeile geschrieben,

Code: Alles auswählen

NewList File1.s()

RandomSeed(0)   ;Selber Randomseed, damit immer die selben Ergebnisse kommen
Define i.i
For i = 0 To 1000000
   If AddElement(File1())
      File1() = "Dies ist ein Teststring_" + Str(Random(1000000))
   EndIf
Next

Define Time.i = ElapsedMilliseconds()
SortList(File1(), #PB_Sort_Ascending)
;---------------------------------------------------------
If FirstElement(File1())
   Define *File1Last.String = @File1()    ; Zuweisung der Adresse von File1()
   While NextElement(File1())               ; Anderung File1() auf das nächste Element
      If *File1Last\s = File1()                 ; *File1Last\s steht beinhaltet noch das vorhergendene, welches vor NextElement gültig war.
         j + 1                                        ; warum zeigt*File1Last\s nach NextElement noch nicht auf den Inhalt nach NextElement(File1())
      EndIf
      *File1Last.String = @File1()            ; hier wird erst *File1Last.String auf die Adresse gesetzt, die mit NextElement gesetzt wurde
   Wend                                              ;
EndIf
;---------------------------------------------------------
Time = ElapsedMilliseconds() - Time

MessageRequester("Info", "Zeit: " + Str(Time) + #CRLF$ + "Doppelt: " + Str(j))

Re: NewList

Verfasst: 07.05.2013 17:02
von NicTheQuick
Eine LinkedList besteht aus einzelnen Elementen, die untereinander verlinkt sind, das heißt benachbarte Elemente kennen sich, also jedes Element kennt das Element vor und nach ihm, falls ein solches existiert.
Wenn man in PB mit Listen arbeitet, gibt es immer ein aktuelles Element, das man mit ListenName() ansprechen kann. Ruft man dann 'NextElement(ListenName())', wird einfach der 'rechte' Nachbar des aktuellen Elements zum aktuellen Element. Gibt es kein solches, dann gibt 'NextElement()' eben 0 zurück. Das heißt: Nur weil das aktuelle Element sich ändern, ist das vorher aktuelle Element immer noch an der selben Stelle im Speicher und somit zeigt der in '*File1Last' gespeicherte Pointer immer noch auf das vorherige Element.

Falls du das jetzt dennoch nicht verstehst, dann weißt du noch nicht genau wie Pointer funktionieren oder wie allgemein der Speicher in einem Computer funktioniert.

Re: NewList

Verfasst: 07.05.2013 20:33
von Martin66119
Vielen vielen Dank NicTheQuick!

Re: NewList

Verfasst: 07.05.2013 21:14
von Martin66119
Hallo NicTheQuick,

ich habe noch eine Frage an dich. Kann man folgenden Code irgendwie durch Pointer oder so noch schneller machen?

Code: Alles auswählen

             While NextElement(Liste2())            
                If FindMapElement(Datei1(), Liste2()) 
                 Else
                  AddMapElement(Datei4(), Liste2(),#PB_Map_ElementCheck)
                  EndIf              
               Wend 

Re: NewList

Verfasst: 07.05.2013 21:39
von NicTheQuick
Nicht wirklich. Da müsste ich eher wissen, was überhaupt bezweckt werden soll. Womöglich gehst du es grundlegend falsch an bzw. es gibt eine viel schnellere Möglichkeit das zu tun, was du vorhast.
Ansonsten hilft vielleicht einfach die Map-Größe zu ändern, indem du den entsprechenden Parameter bei 'NewMap' nutzt.

Du kannst den Code übrigens hübscher mit einem 'Not' schreiben. Dadurch wird es aber nicht wirklich schneller.

Code: Alles auswählen

While NextElement(Liste2())
	If Not FindMapElement(Datei1(), Liste2())
		AddMapElement(Datei4(), Liste2())
	EndIf             
Wend

Re: NewList

Verfasst: 07.05.2013 22:25
von Martin66119
Nachmals Danke!

Ich habe zwei Listen, in der einige Zeichenketten idnetisch. Nun möchte ich herausfinden welche nur in der Liste 1 enthalten sind und welche nur in der Liste 2.

Dazu habe ich folgenden Code, der bisher bei mir die schnellste Lösung ist. Da ich aber ein absoluter anfänger bin, kann ich mir nicht vorstellen das es nicht deutlich schneller geht. Ich möchte aber auf jedenfall in zwei Schleifen (ggf. auch verschachtelt) bleiben.

Code: Alles auswählen

            While NextElement(Liste1())
              If Not FindMapElement(Datei2(), Liste1())
                AddMapElement(Datei3(), Liste1(),#PB_Map_ElementCheck)
               EndIf  
             Wend

            ;--------------------------------

             While NextElement(Liste2())            
                If Not FindMapElement(Datei1(), Liste2()) 
                  AddMapElement(Datei4(), Liste2(),#PB_Map_ElementCheck)
                  EndIf              
               Wend 

Re: NewList

Verfasst: 08.05.2013 10:51
von Martin66119
Hallo NicTheQuick,

folgender Code (im Prinzip) müsste doch sehr schnell sein. Nur wie das geht, weiß ich nicht.

Code: Alles auswählen

Anzahl = 3
;-----------------------------------------------------------
*pFile1.String = AllocateMemory(20000000)
*pFile2.String = AllocateMemory(20000000)
*pFile3.String = AllocateMemory(20000000)
;-----------------------------------------------------------
Define *pFile1.String
*pFile1 = @File1
*pFile1\s = "File1"    ;schreibe ab der ersten Adresse zu AllocateMemory "File1" mit 0 als Stringabschluss
Debug *pFile1\s       
;-----------------------------------------------------------
RandomSeed(0)   ;
Define i.i

For i = 0 To Anzahl
  String$ ="Dies ist ein Teststring_" + Str(Random(Anzahl))
  CopyMemoryString(String$, ???????)  ; schreibe ab der ersten Adresse hinter "File" den eingelesenen String mit 0 als Stringabschluss
Next
;-----------------------------------------------------------
Define *pFile2.String
*pFile2 = @File2
*pFile2\s = "File2"    ; schreibe ab der ersten Adresse zu AllocateMemory "File2" mit 0 als Stringabschluss
Debug *pFile2\s       ;  

RandomSeed(0)   
Define i.i

For i = 0 To Anzahl
  String$ ="Dies ist ein Teststring_" + Str(Random(Anzahl))
  CopyMemoryString(String$, ?????????)   ; schreibe ab der ersten Adresse hinter "File2" den eingelesenen String mit 0 als Stringabschluss
Next
;-----------------------------------------------------------  
For i = 0 To Anzahl
  For j = 0 To Anzahl
    If Not CompareMemoryString( , ) ;  Vergleiche String 1 aus dem Memory 1 mit allen Strings des Memory 2
      CopyMemoryString()    ; schreibe ab der Adresse AllocateMemory     "File3" den String der im Memory 1 drin ist aber in Memory 2 nicht gefunden wurde mit 0 als Zeichenabschluss       
    EndIf
    
  Next
Next


Debug ??????????; Zeige alle Strings an die nicht gefunden wurden

Re: NewList

Verfasst: 08.05.2013 12:40
von NicTheQuick
:shock:

Entschuldige, aber das ist eine ganz schöne Pointervergewaltigung, die du da treibst. Schon ab der 7. Zeile macht dein Code keinen Sinn mehr. Was ist denn 'File1' überhaupt? Und die doppelt verschachtelte For-Loop am Ende braucht eben Anzahl² · (durchschnittliche Stringlänge) an Zeit. Also wesentlich länger als alles, was wir dir schon vorgeschlagen haben. Bevor du hier mit Pointern um dich wirfst, solltest du erst mal an kleinen Beispielen lernen wie sie funktionieren. Aber dafür hab ich keine Zeit. Da gibt es genügend Threads hier im Forum.
Du kannst deinen Code noch schneller machen, indem du Threads benutzt. Aber wozu brauchst du überhaupt so einen Affenzahn? War das Problem nicht schon in einem anderen Thread von dir gelöst, wo das ganze nur noch etwas um die 100 ms gedauert hat oder so?

Re: NewList

Verfasst: 08.05.2013 14:31
von Martin66119
Hallo NicTheQuick,

da ich eigengtlich keine Ahnung habe, entschuldige bitte meine Frage zu dem Code. ich dachte das sei nicht so aufwendig.

Mir geht es nur darum zu schauen, wie schnell PB eine Zeichenkette durchsuchen kann, wenn man eine optimale Lösung hat.

Danke