Seite 2 von 2

Re: Stringvergleich

Verfasst: 24.04.2013 15:01
von NicTheQuick
Genau. Es kommt halt immer drauf an, was man will. Die Vergleichroutine selbst ist natürlich das schnellste, was geht.
Es gibt es aber auch die Möglichkeit eine temporäre sortierte Liste zu erstellen ohne die Ursprungslisten zu ändern. Oder das ganze in ein temporäres Array zu betten. Vielleicht ist das auch nochmal schneller als LinkedLists.

Re: Stringvergleich

Verfasst: 25.04.2013 20:40
von Martin66119
Leider verstehe ich den Code nicht.

Nun habe ich mal mit "Map" gearbeitet. Bei 10000 Daten in Datei 1 und 10000 in Datei 2 dauert ein Durchlauf kann 170ms.

Win7
Netbook; 1,7 GHZ; MonoCore

Code: Alles auswählen

NewList Liste1.s()
NewList Liste2.s()
NewList Liste3.s()
NewList Liste4.s()
NewList DateiName.s()
NewMap Datei1.s()
NewMap Datei2.s()


If OpenWindow(0, 100, 150, 500, 300, "Dateivergleich")
  If CreateMenu(0, WindowID(0))
    MenuTitle("Datei")
      MenuItem( 5, "Datei_1")
      MenuItem( 6, "Datei_2")
      MenuBar()
      MenuItem( 7, "&Quit")

    MenuTitle("Vergleich")
      MenuItem( 8, "Dateivergleich")
      
    MenuTitle("?")
      MenuItem(11, "About")

  EndIf
  
  ; This is the 'event loop'. All the user actions are processed here.
  ; It's very easy to understand: when an action occurs, the Event
  ; isn't 0 and we just have to see what have happened...
    
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Menu
        Select EventMenu()  
          Case 5:
            FileName1$ = OpenFileRequester("Wählen die erste der beiden zu vergleichenden Dateien aus", "F:\Dateivergleich", "", 0)
            ReadFile(1,FileName1$)
            While Eof(1)=0
              Zeile.s=ReadString(1)  
              AddMapElement(Datei1(),Zeile.s,#PB_Map_ElementCheck) 
              AddElement(Liste1())
              Liste1() = Zeile.s
            Wend
            CloseFile(1)

            Anzahl_Datei1 = MapSize(Datei1())-1

            TextGadget(5, 10,  10, 480, 30, "Datei_1: " + FileName1$ +  Chr(10) + Chr(13) + "Anzahl: "  + StrU(Anzahl_Datei1))            

          Case 6: 
            FileName2$ = OpenFileRequester("Wählen die zweite der zu vergleichenden Dateien aus", "F:\Dateivergleich", "", 0)
            ReadFile(1,FileName2$)

            While Eof(1)=0
              Zeile.s=ReadString(1)
              AddMapElement(Datei2(),Zeile.s,#PB_Map_ElementCheck)
              AddElement(Liste2())
              Liste2() = Zeile.s
            Wend
            CloseFile(1)

            Anzahl_Datei2 = MapSize(Datei2()) - 1
            TextGadget(6, 10,  40, 480, 30, "Datei_2: " + Filename2$ +  Chr(10) + Chr(13) +"Anzahl: " + StrU(Anzahl_Datei2))
          Case 7:
            End
            
          Case 8:
            DeleteFile("Daten nur in Datei 2.txt")
            DeleteFile("Doppelte Einträge.txt")

            StartTime = ElapsedMilliseconds() 
            
            ;-----------------------------------
            
              ForEach Liste1()
              Vergleich$ = Liste1()
              If FindMapElement(Datei2(), Vergleich$)   
                ;DeleteMapElement(Datei2(),Vergleich$)
                  Else
                    AddElement(Liste3())
                    Liste3() = Vergleich$
                    ;DeleteMapElement(Datei2(),Vergleich$)
                  EndIf              
              Next

            ;--------------------------------
            
              ForEach Liste2()
              Vergleich$ = Liste2()
              If FindMapElement(Datei1(), Vergleich$) 
                ;DeleteMapElement(Datei1(),Vergleich$)
                  Else
                    AddElement(Liste4())
                    Liste4() = Vergleich$  
                    ;DeleteMapElement(Datei1(),Vergleich$)
                  EndIf              
              Next          
            
            ;---------------------------------            
            
            Time =ElapsedMilliseconds() - StartTime
            If CreateFile(0, "Daten nur in Datei 2.csv") 
              ForEach Liste3()
                WriteStringN(0, Liste3())  
               Next
               CloseFile(0)                       
            Else
              MessageRequester("Information","Konnte Datei nicht erstellen!")
            EndIf
            If CreateFile(0, "Daten nur in Datei 1.csv") 
              ForEach Liste4()
                 WriteStringN(0, Liste4())  
              Next
                CloseFile(0)                       
            Else
               MessageRequester("Information","Konnte Datei nicht erstellen!")
            EndIf
           
            Anzahl_Datei3 = ListSize(Liste3())
            Anzahl_Datei4 = ListSize(Liste4())
            

            TextGadget(3, 10,  190, 250, 20, "Anzahl Datei2/Datei1: " + Str(Anzahl_Datei3))
            TextGadget(4, 10,  220, 250, 20, "Anzahl Datei1/Datei2: " + Str(Anzahl_Datei4))
            
            MessageRequester("Auswertezeit", Str(Time))
          Case 11 ; About
            MessageRequester("About", "Hilfsmittel zum Vergleich zweier Dateien", 0)
            
          Default
            MessageRequester("Info", "MenuItem: "+Str(EventMenu()), 0)
        EndSelect

      Case #PB_Event_CloseWindow
        Quit = 1

    EndSelect

  Until Quit = 1

EndIf

End  


Re: Stringvergleich

Verfasst: 27.04.2013 23:39
von Martin66119
Guten Abend,

nun habe ich noch ein wenig geändert. Das Umspeichern in die Hilfsvariable "Vergleich§" war natürlich nicht erforderlich. Nun hier der aktuelle Code.

Gibt es irgendeine Möglichkeit die Schleife noch etwas zu beschleunigen.

Schon einmal Danke für die Hilfe und auch nochmal Danke für die bisherige Hilfe.

Code: Alles auswählen

NewList Liste1.s()
NewList Liste2.s()
NewList Liste3.s()
NewList Liste4.s()

NewMap Datei1.s()
NewMap Datei2.s()

If OpenWindow(0, 100, 150, 500, 300, "Dateivergleich")
  If CreateMenu(0, WindowID(0))
    MenuTitle("Datei")
      MenuItem( 5, "Datei_1")
      MenuItem( 6, "Datei_2")
      MenuBar()
      MenuItem( 7, "&Quit")

    MenuTitle("Vergleich")
      MenuItem( 8, "Dateivergleich")
      
    MenuTitle("?")
      MenuItem(11, "About")

  EndIf
  
  ; This is the 'event loop'. All the user actions are processed here.
  ; It's very easy to understand: when an action occurs, the Event
  ; isn't 0 and we just have to see what have happened...
    
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Menu
        Select EventMenu()  
          Case 5:
            FileName1$ = OpenFileRequester("Wählen die erste der beiden zu vergleichenden Dateien aus", "F:\Dateivergleich", "", 0)
            ReadFile(1,FileName1$)
            While Eof(1)=0
              Zeile.s=ReadString(1)  
              AddMapElement(Datei1(), Zeile.s,#PB_Map_ElementCheck) 
              AddElement(Liste1())
              Liste1() = Zeile.s
            Wend
            CloseFile(1)

            Anzahl_Datei1 = MapSize(Datei1())-1

            TextGadget(5, 10,  10, 480, 30, "Datei_1: " + FileName1$ +  Chr(10) + Chr(13) + "Anzahl: "  + StrU(Anzahl_Datei1))            

          Case 6: 
            FileName2$ = OpenFileRequester("Wählen die zweite der zu vergleichenden Dateien aus", "F:\Dateivergleich", "", 0)
            ReadFile(1,FileName2$)

            While Eof(1)=0
              Zeile.s=ReadString(1)
              AddMapElement(Datei2(),Zeile.s,#PB_Map_ElementCheck)
              AddElement(Liste2())
              Liste2() = Zeile.s
            Wend
            CloseFile(1)
            Anzahl_Datei2 = MapSize(Datei2()) - 1
            TextGadget(6, 10,  40, 480, 30, "Datei_2: " + Filename2$ +  Chr(10) + Chr(13) +"Anzahl: " + StrU(Anzahl_Datei2))
          Case 7:
            End
            
          Case 8:
            DeleteFile("Daten nur in Datei 2.txt")
            DeleteFile("Doppelte Einträge.txt")

            StartTime = ElapsedMilliseconds() 
            
            ;-----------------------------------
            
              ForEach Liste1()
              If FindMapElement(Datei2(), Liste1())
              Else
                 AddElement(Liste3())
                 Liste3() = Liste1()
                  EndIf              
              Next

            ;--------------------------------
            
              ForEach Liste2()            
                If FindMapElement(Datei1(), Liste2()) 
                  Else
                    AddElement(Liste4())
                    Liste4() = Liste2() 
                  EndIf              
                Next   
                         
            ;---------------------------------            
            
            Time =ElapsedMilliseconds() - StartTime
            If CreateFile(0, "Daten nur in Datei 2.csv") 
              ForEach Liste3()
                WriteStringN(0, Liste3())  
               Next
               CloseFile(0)                       
            Else
              MessageRequester("Information","Konnte Datei nicht erstellen!")
            EndIf
            If CreateFile(0, "Daten nur in Datei 1.csv") 
              ForEach Liste4()
                 WriteStringN(0, Liste4())  
              Next
                CloseFile(0)                       
            Else
               MessageRequester("Information","Konnte Datei nicht erstellen!")
            EndIf
           
            Anzahl_Datei3 = ListSize(Liste3())
            Anzahl_Datei4 = ListSize(Liste4())
            

            TextGadget(3, 10,  190, 250, 20, "Anzahl Datei2/Datei1: " + Str(Anzahl_Datei3))
            TextGadget(4, 10,  220, 250, 20, "Anzahl Datei1/Datei2: " + Str(Anzahl_Datei4))
            
            MessageRequester("Auswertezeit", Str(Time))
          Case 11 ; About
            MessageRequester("About", "Hilfsmittel zum Vergleich zweier Dateien", 0)
            
          Default
            MessageRequester("Info", "MenuItem: "+Str(EventMenu()), 0)
        EndSelect

      Case #PB_Event_CloseWindow
        Quit = 1

    EndSelect

  Until Quit = 1

EndIf

End  


Re: Stringvergleich

Verfasst: 28.04.2013 00:19
von Martin66119
Hatte vergessen was zur Geschwindigkeit zu sagen:

Rechner: Netbool 1,7 GHz (MonoCore); Win7
Datei 1 ca. 11000 Zeilen mit jeweils ca. 120 Zeichen pro Zeile
Darei 2 ca. 10000 Zeilen mit jeweils ca. 120 Zeichen pro Zeile

Zeit: 110ms

Re: Stringvergleich

Verfasst: 28.04.2013 12:42
von matbal
Eine Map ist am schnellsten, wenn sie genügend Slots für die Elemente hat. Es wäre daher sinnvoll, die Map mit mehr Slots zu erstellen. Zum Testen kannst du beim Erstellen der Map in die Klammer einfach mal 10000 Eintragen. Das sollte noch etwas bringen.

Das Problem ist, daß man vor dem Laden der Datei die Anzahl der Elemente noch nicht kennt. Ich denke daher, daß es besser wäre, erst nur die LinkedList zu füllen. Danach kennst du die Anzahl der Elemente und kannst die Map auch mit der optimalen Anzahl von Slots anlegen.


Mir ist aufgefallen, daß du vor dem Laden einer Datei die LinkedList nicht leerst. Das gibt falsche Ergebnisse, wenn sie von einem vorherigen Programmlauf schon Daten enthält.

Re: Stringvergleich

Verfasst: 28.04.2013 16:34
von Martin66119
Vielen Dank matbal,

ich habe deine Vorschläge umgesetzt. Die Bearbeitungszeit hat sich nun von 110ms auf 62ms reduzuiert, Nicht schlecht die kleine Änderung.

Gibt es nicht noch eine Möglichkeit in der Schleife was zu optimieren?
Z.B. Delete ...; Doch wenn ich das mache, verlängert sich die Ausführung. Eigentlich müsste es doch schneller gehen, da die Datei immer kleiner wird. Aber das ist nich so!

Code: Alles auswählen

ForEach Liste1()
  If FindMapElement(Datei2(), Liste1())
    ;DeleteMapElement(Datei2())
  Else
    AddElement(Liste3())
    Liste3() = Liste1()
  EndIf  
Next
Nun habe ich die Liste noch durch eine Map ersetzt: Ergebnis: 47ms

Code: Alles auswählen

ForEach Liste1()
  If FindMapElement(Datei2(), Liste1())
    ;DeleteMapElement(Datei2())
  Else
    AddMapElement(Datei3(), Liste1(),#PB_Map_ElementCheck)
    ; AddElement(Liste3())
    ; Liste3() = Liste1()
  EndIf  
Next
Vielen Vielen Dank für die Hilfe

__________________________________________________
Code-Tags hinzugefügt
28.04.2013
RSBasic

Re: Stringvergleich

Verfasst: 29.04.2013 20:25
von Martin66119
Gutnen Abend!

Kann man mit PureBasic voneinander unabhängige Programmteile zwei verschiedenen Prozessorkernen zuweisen?

z.B eine Berechnung in einer Schleife 1 der Kern 1
und eine andere Berechnung in einer Schleife 2 dem Kern 2

Re: Stringvergleich

Verfasst: 29.04.2013 23:53
von RSBasic
Du kannst mehrere Sachen aufteilen: http://www.rsbasic.de/aktualisierung/wi ... rteilen.pb

Re: Stringvergleich

Verfasst: 04.05.2013 14:47
von Martin66119
Vielen Dank RSBasic,

bevor ich mit mehreren Kernen arbeiten kann, muss ich wohl zuerst noch einiges lernen.

Wie mache ich folgendes am besten?

Nun habe ich es hinbekommen die beiden zu vergleichenden Strings in den Speicher zu schreiben. Das „Null-Zeichen“ am Ende des jeweilig kopierten Strings wird aber mit dem Code (siehe unten) nicht eingefügt bzw. überschrieben. Wenn ich nach jedem Schreibvorgang die Adresse um eins erhöhe klappt es. Ob das so aber korrekt und auch sinnvoll ist, weiß ich nicht.

Wenn man das so macht, dann müsste es auch mit dem „CompareMemoryString“ klappen, ohne dass ich eine Längenangabe mache. Wenn ich CompareMemory nehme brauche ich immer eine Längenangabe. deshalb habe ich zwei Hilfsfelder angelegt, in die ich die Länge jedes Strings eintrage.

Kann mir bitte jemand weiterhelfen, wie ich es am besten hinbekomme, mit CompareMemoryString oder comparememory in einer Schleife die Strings vergleichen kann.

Schon einmal vielen Dank für die Hilfe.

Hier der Code:

Code: Alles auswählen

Dim a.s(20000)
Dim b.s(20000)
Dim c.s(20000)
Dim a_laenge(20000)
Dim b_laenge(20000)

a(1) = "Wald"
a(2) = "Baum"
a(3) = "Ast"
a(4) = "Blatt"

b(1) = "Hund"
b(2) = "Maus"
b(3) = "Katze"
b(4) = "Ast"
b(5) = "Vogel"
b(6) = "Wald"


Anzahl_a = 4              
Anzahl_b = 6            
            
  String1$ = a(1)
  *String1 = @String1$   
  
  String2$ = b(1)
  *String2 =@String2$
  
  *BufferString1 = AllocateMemory(10000000)
  *PointerString1 = *BufferString1
  
  *BufferString2 = AllocateMemory(10000000)
  *PointerString2 = *BufferString2 
;-----------------------------------------------------------  

Ergebnis = CopyMemoryString(a(1), @*PointerString1)
a_laenge(1) = Len(a(1))
 
For i= 2 To Anzahl_a
  CopyMemoryString(a(i)) 
  a_laenge(i) = Len(a(i))
  ;Debug PeekS(*BufferString1)
Next
 
;----------------------------------------------------------- 
  CopyMemoryString(b(1), @*PointerString2)
  b_laenge(1) = Len(b(1))
 For i = 2 To Anzahl_b
   CopyMemoryString(b(i))
   b_laenge(i) = Len(b(i))
 Next
  ;---------------------------------------------------------- 
  ;Debug PeekS(*BufferString1)
  ;Debug PeekS(*BufferString2)
  ;StringBuffer1$ = PeekS(*BufferString1)
  ;Debug StringBuffer1$ 
   *AdresseString2 = *BufferString2
  StartTime = ElapsedMilliseconds() 
  For i = 1 To Anzahl_b
    ;Debug b(i)
    ; How do I have to set and calculate *BufferString2 in order to use the function CompareMemory ()????????
    MessageRequester("",PeekS(*BufferString1, a_laenge(1)) + "  " + PeekS(*AdresseString2, b_laenge(i)))
     If CompareMemory(*BufferString1, *AdresseString2, b_laenge(i)) = 0 ;???????????????????
       NichtGefunden = NichtGefunden + 1     
       c(NichtGefunden) = PeekS(*BufferString2)       
     Else

     EndIf
   *AdresseString2 = *AdresseString2 + b_laenge(i)
   Next
   Time =ElapsedMilliseconds() - StartTime
   MessageRequester("Auswertezeit", Str(Time))
   MessageRequester("","Nicht gefunden" +  Str(NichtGefunden))