Durchlauf von Map mit ForEach

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
TroaX
Beiträge: 661
Registriert: 08.03.2013 14:27
Computerausstattung: PC: Ryzen 9 3950X, 96 GB RAM, RX6800XT, 2.5 TB SSD, 21:9 Display, Pop_OS! | Lappi: Ryzen 7 5800H, 16 GB RAM, 1 TB SSD, Pop_OS!
Wohnort: NRW
Kontaktdaten:

Re: Durchlauf von Map mit ForEach

Beitrag von TroaX »

techniker hat geschrieben: 20.01.2023 14:02Und wie soll ich die enthaltenen Werte sonst prüfen, als sequentielles abarbeiten?
Mein Vorschlag: In dem man Werte mit Hilfe einer eigenen Setter-Prozedur in ein Element schreibt und dabei auf eine Dublette prüft. Dann muss die Schleife nur ein einziges mal beim schreiben eines Wertes durchlaufen, wenn du einen neuen Eintrag einsetzt. Dadurch verteilt sich die Last in den Arbeitsfluss und muss nicht auf einen Schlag erbracht werden.
PC: Ryzen 9 3950X | 96 GB RAM | RX6800XT | 2,5 TB NVMe | Pop_OS!
Notebook: 16" 3:2 | Ryzen 7 5800H | 16 GB RAM | Radeon Vega | 1TB NVMe | Pop_OS!
NAS: Fritz.Box :lol:
Coding: Purebasic 6.04 | PHP | HTML | CSS | Javascript
Benutzeravatar
techniker
Beiträge: 160
Registriert: 27.01.2016 11:08
Wohnort: BY

Re: Durchlauf von Map mit ForEach

Beitrag von techniker »

Ja, das wäre eine Überlegung wert..
Never change a running system - Never run a changed system!
(PB 6.03 LTS [x86])
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Durchlauf von Map mit ForEach

Beitrag von mk-soft »

SQLite Datenbank im Speicher ...

Update
- Add rowID

Code: Alles auswählen


UseSQLiteDatabase()

Procedure CheckDatabaseUpdate(Database, Query$)
   Result = DatabaseUpdate(Database, Query$)
   If Result = 0
      Debug DatabaseError()
   EndIf
   
   ProcedureReturn Result
EndProcedure

DatabaseFile$ = ":memory:"

If OpenDatabase(0, DatabaseFile$, "", "")

  CheckDatabaseUpdate(0, "CREATE TABLE food (rowID INTEGER PRIMARY KEY AUTOINCREMENT, name CHAR(50), weight INT)")

  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('apple', '10')")
  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('apple', '10')")
  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('apple', '10')")
  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('pear', '5')")
  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
  CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
  
  ;If DatabaseQuery(0, "SELECT * FROM food WHERE weight > 7")
  If DatabaseQuery(0, "SELECT name, count(name), sum(weight) FROM food GROUP BY name")
  
     While NextDatabaseRow(0)
        Debug GetDatabaseString(0, 1) + " Count = " + GetDatabaseLong(0, 2)  + " Summe = " + GetDatabaseLong(0, 3)
     Wend
  
     FinishDatabaseQuery(0)
  EndIf
  
  CloseDatabase(0)
Else
  Debug "Can't open database !"
EndIf
Zuletzt geändert von mk-soft am 20.01.2023 14:28, insgesamt 1-mal geändert.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
techniker
Beiträge: 160
Registriert: 27.01.2016 11:08
Wohnort: BY

Re: Durchlauf von Map mit ForEach

Beitrag von techniker »

! DAS IST EINE GENIALE IDEE !

Bedeutet zwar etwas Arbeit für die Umgestaltung, aber ich denke, dass sich das lohnen könnte.
Vielen dank für den Tip!
Never change a running system - Never run a changed system!
(PB 6.03 LTS [x86])
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Durchlauf von Map mit ForEach

Beitrag von mk-soft »

Lange Version mit Ausgabe Fenster und rowID

Code: Alles auswählen

;-TOP

; Comment : ShowDatabaseItems
; Author  : mk-soft
; Version : v1.03.1
; Create  : 12.02.2017
; Update  : 19.08.2022

EnableExplicit

; ***************************************************************************************

Procedure GetTextWidth(Text.s, FontID.i = 0)
  Static image
  Protected result
  
  If Not image
    image = CreateImage(#PB_Any, 1, 1)
  EndIf
  
  If image And StartDrawing(ImageOutput(image))
    If FontID
      DrawingFont(FontID)
    EndIf
    result = TextWidth(Text)
    StopDrawing()
  EndIf
  ProcedureReturn result
EndProcedure

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

Procedure ClearGadgetColumns(Gadget)
  CompilerIf #PB_Compiler_Version <= 551
    ClearGadgetItems(Gadget)
    While GetGadgetItemText(Gadget, -1, 0)
      RemoveGadgetColumn(Gadget, 0)
    Wend
  CompilerElse
    RemoveGadgetColumn(Gadget, #PB_All)
  CompilerEndIf
EndProcedure

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

Procedure CountGadgetColumns(Gadget)
  Protected result
  CompilerIf #PB_Compiler_Version <= 551
    While GetGadgetItemText(Gadget, -1, result)
      result + 1
    Wend
  CompilerElse
    result = GetGadgetAttribute(Gadget, #PB_ListIcon_ColumnCount)
  CompilerEndIf
  ProcedureReturn result
EndProcedure

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

Procedure FitColumnWidth(Gadget, Column = #PB_All)
  Protected columns, rows, col, row, width, max, dx
  Static help_gadget
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    If Column = #PB_All
      columns = CountGadgetColumns(Gadget) - 1
      For col = 0 To columns
        SendMessage_(GadgetID(Gadget), #LVM_SETCOLUMNWIDTH, col, #LVSCW_AUTOSIZE_USEHEADER)
      Next
    Else
      SendMessage_(GadgetID(Gadget), #LVM_SETCOLUMNWIDTH, Column, #LVSCW_AUTOSIZE_USEHEADER)
    EndIf
    
  CompilerElse
    rows = CountGadgetItems(Gadget) - 1
    dx = GetTextWidth("X", GetGadgetFont(Gadget))
    If Column = #PB_All
      columns = CountGadgetColumns(Gadget) - 1
      For col = 0 To columns
        For row = -1 To rows
          width = Len(GetGadgetItemText(Gadget, row, col))
          If width > max
            max = width
          EndIf
        Next
        width = max * dx + 4
        SetGadgetItemAttribute(Gadget, 0, #PB_ListIcon_ColumnWidth, width, col)
        width = 0
        max = 0
      Next
    Else
      For row = -1 To rows
        width = Len(GetGadgetItemText(Gadget, row, Column))
        If width > max
          max = width
        EndIf
      Next
      width = max * dx + 4
      SetGadgetItemAttribute(Gadget, 0, #PB_ListIcon_ColumnWidth, width, Column)
    EndIf
    
  CompilerEndIf
  
EndProcedure

Procedure ShowDatabaseRows(Gadget, DBase, NbDecimals = 0, Hide = #False)
  Protected result.i, columns.i, index.i, size.i, text.s, fltVal.f, dblVal.d
  
  Repeat
    If GadgetType(Gadget) <> #PB_GadgetType_ListIcon
      Break
    EndIf
    If Not IsDatabase(DBase)
      Break
    EndIf
    HideGadget(Gadget, Hide)
    ClearGadgetItems(Gadget)
    ClearGadgetColumns(Gadget)
    columns = DatabaseColumns(DBase) - 1
    Dim ColumnType(columns)
    For index = 0 To columns
      ColumnType(index) = DatabaseColumnType(DBase, index)
      text = DatabaseColumnName(DBase, index)
      size = GetTextWidth(text) + 12
      AddGadgetColumn(Gadget, index, text, size)
    Next
    While NextDatabaseRow(DBase)
      text = ""
      For index = 0 To columns
        Select ColumnType(index)
          Case #PB_Database_Float
            fltVal = GetDatabaseFloat(DBase, index)
            text + FormatNumber(fltVal, NbDecimals) + #LF$
          Case #PB_Database_Double
            dblVal = GetDatabaseDouble(DBase, index) ; <- Bug Linux
            ;dblVal = ValD(GetDatabaseString(DBase, index))
            text + FormatNumber(dblVal, NbDecimals) + #LF$
          Default
            text + GetDatabaseString(DBase, index) + #LF$
        EndSelect
      Next
      AddGadgetItem(Gadget, -1, text)
    Wend
    FinishDatabaseQuery(DBase)
    HideGadget(Gadget, #False)
    result = CountGadgetItems(Gadget)
  Until #True
  ProcedureReturn result
  
EndProcedure

; ***************************************************************************************

CompilerIf #PB_Compiler_IsMainFile
  
  ; Constant
  Enumeration ;Window
    #Main
  EndEnumeration
  
  Enumeration ; Menu
    #Menu
  EndEnumeration
  
  Enumeration ; MenuItems
    #MenuExitApplication
  EndEnumeration
  
  Enumeration ; Gadgets
    #List
    #Edit
  EndEnumeration
  
  Enumeration ; Statusbar
    #Status
  EndEnumeration
  
  ; Global Variable
  Global ExitApplication
  
  ; Functions
  
  UseSQLiteDatabase()
  
  Procedure CheckDatabaseUpdate(Database, Query$)
    Protected Result = DatabaseUpdate(Database, Query$)
    If Result = 0
      Debug DatabaseError()
    EndIf
    ProcedureReturn Result
  EndProcedure
  
  Procedure CreateDummyDatabase(DBase)
    If OpenDatabase(DBase, ":memory:", "", "")
      CheckDatabaseUpdate(0, "CREATE TABLE food (rowID INTEGER PRIMARY KEY AUTOINCREMENT, name CHAR(50), weight INT)")
      
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('apple', '10')")
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('apple', '10')")
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('apple', '10')")
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('pear', '5')")
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
      CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")
    Else
      Debug "Can't open database !"
    EndIf
  EndProcedure
  
  Procedure UpdateWindow()
    Protected x, y, dx, dy, menu, status
    
    menu = MenuHeight()
    If IsStatusBar(#Status)
      status = StatusBarHeight(#Status)
    Else
      status = 0
    EndIf
    x = 0
    y = 0
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - menu - status
    ResizeGadget(#List, x, y, dx, dy)
  EndProcedure
  
  ; Main
  Procedure Main()
    Protected event, style, dx, dy, count
    
    style = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
    dx = 800
    dy = 600
    
    If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, dx, dy, "Main", style)
      
      ; Menu
      CreateMenu(#Menu, WindowID(#Main))
      MenuTitle("Ablage")
      MenuItem(#MenuExitApplication, "Be&enden")
      
      CompilerIf #PB_Compiler_OS = #PB_OS_MacOS 
        ; Mac default menu
        If Not IsMenu(#Menu)
          CreateMenu(#Menu, WindowID(#Main))
        EndIf
        MenuItem(#PB_Menu_About, "")
        MenuItem(#PB_Menu_Preferences, "")
      CompilerEndIf
      
      ; Gadgets
      #ListIconFlags = #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_FullRowSelect | #PB_ListIcon_GridLines
      ListIconGadget(#List, 0, 0, dx, dy, "recid", 100, #ListIconFlags)
      
      ; Statusbar
      CreateStatusBar(#Status, WindowID(#Main))
      AddStatusBarField(#PB_Ignore)
      
      UpdateWindow()
      
      ;-Test database
      CreateDummyDatabase(0)
      
      If DatabaseQuery(0, "SELECT name, count(name), sum(weight) FROM food GROUP BY name")
      ;If DatabaseQuery(0, "SELECT * FROM sqlite_master")
        count = ShowDatabaseRows(#List, 0, 3)
        StatusBarText(#Status, 0, "Items: " + count)
      EndIf
      
      FitColumnWidth(#List)
      
      ; Main Loop
      Repeat
        event = WaitWindowEvent()
        Select event
          Case #PB_Event_Menu
            Select EventMenu()
                CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
                  
                Case #PB_Menu_About
                  
                Case #PB_Menu_Preferences
                  
                Case #PB_Menu_Quit
                  ExitApplication = #True
                  
                CompilerEndIf
                
              Case #MenuExitApplication
                ExitApplication = #True
                
            EndSelect
            
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #List
                
            EndSelect
            
          Case #PB_Event_SizeWindow
            Select EventWindow()
              Case #Main
                UpdateWindow()
                
            EndSelect
            
          Case #PB_Event_CloseWindow
            Select EventWindow()
              Case #Main
                ExitApplication = #True
                
            EndSelect
            
        EndSelect
        
      Until ExitApplication
      
    EndIf
    
  EndProcedure : Main()
  
  End
  
CompilerEndIf
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
jacdelad
Beiträge: 348
Registriert: 03.02.2021 13:39
Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
Wohnort: Riesa
Kontaktdaten:

Re: Durchlauf von Map mit ForEach

Beitrag von jacdelad »

Momomoment...ich kann eine Datenbank einfach im RAM erstellen, indem ich als Dateinamen ":memory:" angebe? Ist das irgendwo niedergeschrieben? Woher weiß man solche Dinge und gibt es noch mehr, dass ich wissen sollte???
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Benutzeravatar
techniker
Beiträge: 160
Registriert: 27.01.2016 11:08
Wohnort: BY

Re: Durchlauf von Map mit ForEach

Beitrag von techniker »

jacdelad hat geschrieben: 20.01.2023 14:34 Momomoment...ich kann eine Datenbank einfach im RAM erstellen, indem ich als Dateinamen ":memory:" angebe? Ist das irgendwo niedergeschrieben? Woher weiß man solche Dinge und gibt es noch mehr, dass ich wissen sollte???
Das gleiche habe ich mich auch gefragt, als ich nichts davon in der Hilfe finden konnte..
Never change a running system - Never run a changed system!
(PB 6.03 LTS [x86])
Benutzeravatar
TroaX
Beiträge: 661
Registriert: 08.03.2013 14:27
Computerausstattung: PC: Ryzen 9 3950X, 96 GB RAM, RX6800XT, 2.5 TB SSD, 21:9 Display, Pop_OS! | Lappi: Ryzen 7 5800H, 16 GB RAM, 1 TB SSD, Pop_OS!
Wohnort: NRW
Kontaktdaten:

Re: Durchlauf von Map mit ForEach

Beitrag von TroaX »

An SQLite database is normally stored in a single ordinary disk file. However, in certain circumstances, the database might be stored in memory.
The special filename ":memory:" can be used anywhere that a database filename is permitted.
Quelle: https://www.sqlite.org/inmemorydb.html
PC: Ryzen 9 3950X | 96 GB RAM | RX6800XT | 2,5 TB NVMe | Pop_OS!
Notebook: 16" 3:2 | Ryzen 7 5800H | 16 GB RAM | Radeon Vega | 1TB NVMe | Pop_OS!
NAS: Fritz.Box :lol:
Coding: Purebasic 6.04 | PHP | HTML | CSS | Javascript
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Durchlauf von Map mit ForEach

Beitrag von mk-soft »

Jahrelange Erfahrung und viel im deutschen und englischen Forum Lesen.

Die PB Hilfe kann nicht alles Enthalten. Vieles muss man dann in den Webhilfen von den verwendeten Libraries nachlesen.
Zum Bespiel wie man eigene Funktionen zum SQLite hinzufügt: SQLite create function
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benubi
Beiträge: 186
Registriert: 22.10.2004 17:51
Wohnort: Berlin, Wedding

Re: Durchlauf von Map mit ForEach

Beitrag von Benubi »

Mit FindMapElement kannst Du prüfen ob das Element schon existiert.

Wenn ein Map Element schnell eingefügt wird, ohne Prüfung (No Element Check), dann wird es _vor_ dem gleichnamigen Element eingefügt (insert). Man kann mit NextMapElement() und MapKey() dann die Mehrfacheinträge abarbeiten bis die Map zu Ende ist oder ein anderer Key erscheint; FindMapElement() ändert ja auch das aktuelle Element.

Die Reihenfolge der Map entspricht der Sortierung nach dem internen Hashwert, und ist nicht alphabetisch. Daher kann ein neues Element an verschiedensten Stellen erscheinen; aber diese Stelle ist quasi mathematisch vorbestimmt, weil der Hashwert aus dem Key berechnet wird - wie eine Prüfsumme. Es wird erst nach dem Hashwert gesucht, dann wird der Key verglichen und sollte es nicht der richtige Key sein wegen einer Hashwert Kollision wird das nächste Element (rechtes Kind-Element vermutlich) mit identischem Hashwert verglichen bis der Key gefunden wurde oder ein anderer Hashwert erscheint oder die Map zu Ende ist (nix gefunden, denn).


Wenn ich mit Maps arbeite dann mache ich meistens ein FindMapElement und wenn nichts da ist ein schnelles einfügen per mit no element check. FindMapElement gibt auch den Struktur-Zeiger zurrück.

Code: Alles auswählen

Procedure CheckUpdateMap(key$,value$, Map MyMap.s())
  If Not FindMapElement(MyMap(), Key$)
        Protected result = AddMapElement(MyMap(), Key$, #PB_Map_NoElementCheck)
        MyMap() = value$
       ProcedureReturn result
  EndIf
  ProcedureReturn #False 
EndProcedure

NewMap fruits.s()

Debug CheckUpdateMap("banana","10",fruits())
Debug CheckUpdateMap("banana","10",fruits())
Debug CheckUpdateMap("banana","10",fruits())
Debug CheckUpdateMap("banana","10",fruits())
Debug CheckUpdateMap("banana","10",fruits())
Debug CheckUpdateMap("apple","10",fruits())
Debug CheckUpdateMap("apple","10",fruits())
Debug CheckUpdateMap("raspberry","10",fruits())

Antworten