FindMapElement

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

Re: FindMapElement

Beitrag von Martin66119 »

Vielen Dank Nic

Kannst du mir noch helfen wie ich folgenden Code zum Laden der zu vergleichenen Listen in deinen code einbauen muss. Es sind Zeichenketten Buchstaben und Ziffern.

Code: Alles auswählen

            StandardFile$ = "*\"   ; anfänglichen Pfad + Dateiname festlegen
            Pattern$ = "Text (*.txt)|*.txt;*.csv|Text (*.csv)|*.pb|Alle Dateien (*.*)|*.*"
            Pattern = 0    ; wir verwenden den ersten von drei möglichen Pattern als Standard
            Filename1$ = OpenFileRequester("Bitte erste Datei zum Vergleich auswählen", StandardFile$, Pattern$, Pattern)
              
             Ergebnis1 = ReadFile(1,FileName1$)
             If Ergebnis1 <> 0
               While Eof(1)=0
               Zeile.s=ReadString(1)          
               AddElement(Liste1())
               Liste1() = Zeile.s
             Wend
             CloseFile(1)          
            EndIf
                     
            StandardFile$ = "*\"   ; anfänglichen Pfad + Dateiname festlegen
            Pattern$ = "Text (*.txt)|*.txt;*.csv|Text (*.csv)|*.pb|Alle Dateien (*.*)|*.*"
            Pattern = 0    ; wir verwenden den ersten von drei möglichen Pattern als Standard
            Filename2$ = OpenFileRequester("Bitte zweite Datei zum Vergleich auswählen", StandardFile$, Pattern$, Pattern)
            
             Ergebnis2 = ReadFile(1,FileName2$)
             If Ergebnis2 <> 0
               While Eof(1)=0
                 Zeile.s=ReadString(1)          
               AddElement(Liste2())
               Liste2() = Zeile.s
               Wend
               CloseFile(1)  
            EndIf 
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 »

Eigentlich musst du doch kaum was ändern. Das findest du schon selbst raus. ;)
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Hallo Nic,

habe es mal versucht. Aber es klappt nicht. Es kommt eine Fehlermeldung wegen EnableExplicit

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
 
ReadFile(1,"D:\PB\ExcelDll\Datei1.csv")
               While Eof(1)=0
               Zeile.s=ReadString(1)          
               AddElement(Liste1())
               Liste1() = Zeile.s
             Wend
             CloseFile(1)          

             ReadFile(1,"D:\PB\ExcelDll\Datei2.csv")
               While Eof(1)=0
                 Zeile.s=ReadString(1)          
               AddElement(Liste2())
               Liste2() = Zeile.s
               Wend
               CloseFile(1)  
            StartTime = ElapsedMilliseconds()  
            diff(liste1(), liste2())
            Time =ElapsedMilliseconds() - StartTime 
        
MessageRequester("Titel", Str(Time), #PB_MessageRequester_YesNoCancel) 

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 man 'EnableExplicit' benutzt, dann muss man zwangsweise alle seine Variablen, Listen, Arrays, usw. deklarieren, d.h. immer 'Define' oder 'Protected' oder vergleichbares wie 'Global', 'Static', usw. nutzen.
Das heißt einfach 'EnableExplicit' entfernen, dann sollte das auch schon funktionieren. Alternativ einfach das ändern, worüber die Fehlermeldung meckert. Eigentlich ganz einfach.

Aber ansonsten ist der Code auch korrekt.
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Klappt nicht. Der Code hängt sich auf.

Habe ich was mit der Def der Liste1() und Liste2() falsch
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 »

Die Fehlerbeschreibung ist jetzt wenig aussagekräftig. Wo hängt sich das Programm auf? Was ist die Fehlermeldung? Was sagt der Debugger?
Ein bisschen mithelfen könntest du schon, damit man dir nicht alles aus der Nase ziehen muss. :wink:

Du kannst mir auch gerne die beiden Dateien geben oder zwei Beispieldateien, bei denen das selbe Problem auftritt.
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Guten Morgen Nic,

vielen Dank!

Ich hatte beim Übertragen der paar Zeilen einen Fehler gemacht. Nun klappts.

Mein Programm: 65ms
Dein Programm 18 ms

Das ist ja viel schneller. Danke. Gibt es in deinem Code noch einen Bereich, der optimierbar ist.

Wo ich mal was versuchen kann.
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 »

Möglicherweise sind die Codes in dem Thread, der von Stargate verlinkt wurde, nochmal etwas schneller. Ich hatte das damals mit HashMaps gelöst und das war auch sehr schnell.

Warum muss es überhaupt so schnell sein? Was ist das Grundproblem? Du willst ganz viele Dateien einlesen und miteinander vergleichen? Oder willst du viele Dateien mit genau einer anderen vergleichen? Wie lange dauert eigentlich das Einlesen der Datei, wenn sie noch nicht vom System gecached wurde?
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Hallo Nic,

ich habe nur ein Netbook mit 1,7 Ghz. Also recht langsam. Es sind ca. 40.000 Datensätze pro Liste. Der Vergleich dauert zwar dann nur ca. 400ms. Mich interessiert aber, wie schnell eine optimale Lösung mit PB ist ohne ASM zu zu verwenden.

Grüße
Martin
Martin66119
Beiträge: 282
Registriert: 03.01.2005 11:36

Re: FindMapElement

Beitrag von Martin66119 »

Hallo Nic,

hier dein Code bei dem ich nur das Einlesen zweier Dateien eingebaut habe. Wieso hast du die Liste list1() und list2() nicht mit einem Pointer realisiert, so wie *onlyIn1.String() und *onlyIn2.String() oder geht das nicht?

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 + "'"
     ;MessageRequester("Information", *onlyIn1()\s, #PB_MessageRequester_Ok)

   Next
   Debug ""
   
   Debug "Zeilen, die nur in Liste 2 vorhanden sind:"
   ForEach *onlyIn2()
     ;MessageRequester("Information", *onlyIn2()\s, #PB_MessageRequester_Ok)
      Debug "'" + *onlyIn2()\s + "'"
   Next
   Debug ""
EndProcedure
; ----------------------Hauptprogramm-----------------------------------
NewList liste1.s()
NewList liste2.s()
Define zeile.s

  Ergebnis1 = ReadFile(1,"D:\PB\ExcelDll\Datei1.csv")
  If Ergebnis1 <> 0
    While Eof(1)=0
      zeile.s=ReadString(1)          
      AddElement(liste1())
      liste1() = Zeile.s
    Wend
    CloseFile(1)          
  EndIf
  Ergebnis1 = ReadFile(1,"D:\PB\ExcelDll\Datei2.csv")
  If Ergebnis1 <> 0
    While Eof(1)=0
      zeile.s=ReadString(1)          
      AddElement(liste2())
      liste2() = Zeile.s
    Wend
    CloseFile(1)          
  EndIf
  StartTime =ElapsedMilliseconds() 
  diff(liste1(), liste2())
  Time =ElapsedMilliseconds() - StartTime             
  MessageRequester("Information", Str(Time), #PB_MessageRequester_Ok)

Antworten