German Liste alphabetisch sortieren

pjo12345

Active Member
Licensed User
Longtime User
Hallo Leute!

Ich brauche mal wieder ein bisschen Hilfe. Ich habe eine Liste mit Daten, z.B.:
Harald, Getränk, 4.0, 0.00, Dummy1, Dummy2, Dummy3, Dummy4, August, Getränk, 35.760000000000005, 0.00, Dummy1, Dummy2, Dummy3, Dummy4, Berta, Getränk, 0.00, 0.00, Dummy1, Dummy2, Dummy3, Dummy4

Für jeden Namen (Harald, August, Berta) sind weitere Daten vorhanden (für Harald z.B.: Getränk, 4.00, 0.00, Dummy1, Dummy2, Dummy3, Dummy4)

Ich möchte diese Liste nun alphabetisch sortieren. Natürlich ohne die Daten zu den jeweiligen Namen durcheinander zu würfeln. Bei Listen gibt es ja diesen SORT Befehl aber das will mir irgendwie nicht gelingen bzw. begreife ich noch nicht so richtig wie das funktionieren soll.
Kann mir da mal einer auf die Sprünge helfen?
Danke schon mal.
 

eurojam

Well-Known Member
Licensed User
Longtime User
Moin Moin,
das geht ziemlich einfach mit b4a. Eigener Type anlegen und in eine Liste geben, danach kannst Du mit liste.sorttype nach jedem Feld sortieren:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Type Kunde (Name As String, Getraenk As String, Feld1 As Int, Feld2 As Double)
    Dim Liste As List


End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Dim k As Kunde
    k.Name = "Harald"
    k.Getraenk = "Cola"
    Liste.Add(k)
    k.Name = "Berta"
    k.Getraenk = "Wein"
    Liste.Add(k)   
    k.Name = "Stefan"
    k.Getraenk = "Bier"
    Liste.Add(k)
   
    'Sortieren
    Liste.SortType("Name", True)
    k= Liste.Get(0)
    Log(k.Name & " " & k.Getraenk)   
    Liste.SortType("Getraenk", True)
    k= Liste.Get(0)
    Log(k.Name & " " & k.Getraenk)   
End Sub

gruß
stefan
 

manhof

Member
Licensed User
Longtime User
Falls Deine Daten aus einer SQLite kommen, kannst du da auch gleich bei der Datenbankabfrage sortieren:
B4X:
SQL1.ExecQuery("SELECT id, name, getraenk, ....,  FROM db ORDER by name")
 

pjo12345

Active Member
Licensed User
Longtime User
Habe jetzt mal ein bisschen damit experimentiert. Dies ist mein Code zum Testen:
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
   
    Type Kunde (Name As String, Getraenk As String, X As Int)
   
   

End Sub

Sub Activity_Create(FirstTime As Boolean)

    Dim Liste As List
    Liste.Initialize()
   
    Dim k As Kunde
       k.Name = "Harald"
    k.Getraenk = "Cola"
    k.X = 1
    Liste.Add(k)
   
    Dim k As Kunde
    k.Name = "Berta"
    k.Getraenk = "Wein"
    k.X = 2
    Liste.Add(k)  
   
    Dim k As Kunde
    k.Name = "Stefan"
    k.Getraenk = "Bier"
    k.X = 3
    Liste.Add(k)
    Log("Liste: " & Liste)
'    File.WriteList(File.DirDefaultExternal,"test.txt",Liste)

    'Sortieren
    Liste.SortType("Name", True)
    For i=0 To Liste.Size-1
        k= Liste.Get(i)
        Log(k.Name & " " & k.Getraenk & " " & k.X) 
    Next
End Sub

Wenn ich diesen ausführe und mir die Liste im Log ansehe kommt dieses:

Liste: (ArrayList) [[Getraenk=Cola, Name=Harald, IsInitialized=false
, X=1], [Getraenk=Wein, Name=Berta, IsInitialized=false
, X=2], [Getraenk=Bier, Name=Stefan, IsInitialized=false
, X=3]]

Warum steht dort immer dieses "IsInitialized=false" in meiner Liste?
 

pjo12345

Active Member
Licensed User
Longtime User
Und gleich noch etwas. Ich möchte die Liste in eine Datei schreiben und sie auch wieder einlesen. Leider klappt das nicht so wie ich mir das denke. Als Beispielcode habe ich mal den Code erweitert.
B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Type Kunde (Name As String, Getraenk As String, X As Int)

End Sub

Sub Activity_Create(FirstTime As Boolean)

    Dim Liste As List
    Liste.Initialize()

    Dim k As Kunde
   k.Name = "Harald"
   k.Getraenk = "Cola"
    k.X = 1
    Liste.Add(k)

    Dim k As Kunde
    k.Name = "Berta"
    k.Getraenk = "Wein"
    k.X = 2
    Liste.Add(k)

    Dim k As Kunde
    k.Name = "Stefan"
    k.Getraenk = "Bier"
    k.X = 3
    Liste.Add(k)

    Log("Liste: " & Liste)

    File.WriteList(File.DirDefaultExternal,"test.txt",Liste)


    'Sortieren

    Liste=File.ReadList(File.DirDefaultExternal,"test.txt")

    Liste.SortType("Name", True)
    For i=0 To Liste.Size-1
        k= Liste.Get(i)
        Log(k.Name & " " & k.Getraenk & " " & k.X)
    Next
End Sub

Das Schreiben der Liste in eine Datei funktioniert. Auch das Lesen. Aber dann bekomme ich eine Fehlermeldung mit der ich nicht zurechtkomme. Bei Liste.SortType("Name",True) tritt der Fehler: java.lang.NoSuchFieldException: Name auf. Ich hoffe, es kann mir einer auf die Sprünge helfen.

Danke
 

MaFu

Well-Known Member
Licensed User
Longtime User
Eigene Typen haben immer ein Feld IsInitialized. Daher erscheint es auch wenn Du die gesamte Liste im Log ausgibst.
Daran siehst Du auch, dass eigene Typen initialisiert werden sollten.
B4X:
Dim k As Kunde
k.Initialize
...

Hast Du dir den Inhalt von test.txt schon mal angesehen?
 

pjo12345

Active Member
Licensed User
Longtime User
B4X:
 Dim k As Kunde
k.Initialize

habe ich eingefügt.

Im Log steht jetzt:
** Activity (main) Create, isFirst = true **
Liste Schreiben: (ArrayList) [[Getraenk=Cola, Name=Harald, IsInitialized=true
, X=1], [Getraenk=Wein, Name=Berta, IsInitialized=true
, X=2], [Getraenk=Bier, Name=Stefan, IsInitialized=true
, X=3]]
Liste Size: 3
Liste Lesen: (ArrayList) [[Getraenk=Cola, Name=Harald, IsInitialized=true, , X=1], [Getraenk=Wein, Name=Berta, IsInitialized=true, , X=2], [Getraenk=Bier, Name=Stefan, IsInitialized=true, , X=3]]
Liste Size: 6
main_activity_create (B4A line: 62)
Liste.SortType("Name", True)
java.lang.NoSuchFieldException: Name
at java.lang.Class.getDeclaredField(Class.java:596)
at anywheresoftware.b4a.objects.collections.List.sortList(List.java:193)
at anywheresoftware.b4a.objects.collections.List.SortType(List.java:181)
at b4a.example.main._activity_create(main.java:437)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
at b4a.example.main.afterFirstLayout(main.java:100)
at b4a.example.main.access$100(main.java:17)
at b4a.example.main$WaitForLayout.run(main.java:78)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)



Mir fallen da einige Sachen auf:
1. Vor dem Schreiben sieht es im Log so aus, dass hinter dem IsInitialized=true ein CRLF zu kommen scheint, denn nach dem Lesen steht die Liste im Log in einer Zeile. Vorher in mehreren.
2. Nach dem Einlesen aus der Datei und Anzeigen im Log stehen hinter IsInitialized=true zwei Kommas. Also statt einem Zeilenumbruch vor dem Schreiben steht nach dem Lesen ein weiteres Komma im Log.
3. Vor dem Schreiben ist die Listengröße = 3 aber nach dem Lesen ist die Listengröße = 6.

Habe das Testprogramm mal als zip angehängt.
 

Attachments

  • Test Sort.zip
    6.2 KB · Views: 205
Last edited:

MaFu

Well-Known Member
Licensed User
Longtime User
File.WriteList arbeitet ausschließlich mit Strings. Alles andere wird beim Schreiben zu einem String konvertiert. Beim Lesen schlägt das allerdings fehl (in Deinem Fall).
Konsequenz: Du kannst WriteList/ReadList nicht verwenden um Typen zu speichern.
Nimm die Lib RandomAccessFile und verwende die Funktionen WriteObject/ReadObject.

Schreiben:
B4X:
Dim raf As RandomAccessFile
raf.Initialize(File.DirDefaultExternal,"test.txt", False)
For i = 0 To Liste.Size - 1
    raf.WriteObject(Liste.Get(i), False, raf.CurrentPosition)
Next
raf.Close
Lesen:
B4X:
Dim raf As RandomAccessFile
Dim Liste As List
Liste.Initialize
Dim k As Kunde
raf.Initialize(File.DirDefaultExternal,"test.txt", True)
Do While raf.CurrentPosition < raf.Size
    k = raf.ReadObject(raf.CurrentPosition)
    Liste.Add(k)
Loop
raf.Close
 

pjo12345

Active Member
Licensed User
Longtime User
Dankeschön, das klappt perfekt. :):):)
 
Top