Stringvergleich

Anfängerfragen zum Programmieren mit PureBasic.
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: Stringvergleich

Beitrag 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.
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: Stringvergleich

Beitrag 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  

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

Re: Stringvergleich

Beitrag 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  

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

Re: Stringvergleich

Beitrag 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
matbal
Beiträge: 261
Registriert: 30.03.2011 20:53

Re: Stringvergleich

Beitrag 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.
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: Stringvergleich

Beitrag 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
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: Stringvergleich

Beitrag 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
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Stringvergleich

Beitrag von RSBasic »

Du kannst mehrere Sachen aufteilen: http://www.rsbasic.de/aktualisierung/wi ... rteilen.pb
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: Stringvergleich

Beitrag 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))

Antworten