[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Looping through an array with FOR EACH


hello

Order in associative array, i.e. collection, is relative. So collection[].sort is relative.

a/ order by reference, i.e. key

b/ order by value, but it depends which data type is used.

c/ order by recording, is just cosmetic, but not really useful.


A good execise, import a CSV file (coma separate value) and convert to collection[]

You notice how to import ( Excell, Libreoffice, ..., wants to know ! ). It expects a formula, a schema to import.

One line is a collection. One data is a cell of column. One column expects a datatype.

Imagine gridview with only collection[]


Now, SQL is forbidden.

Now , you must sort your collection[] using i.e. this column, after this other column, this ...

Try to find the best way to sort.

And finally, write a recursive function if you can.

Complete Gridview  to sort anything.


example.csv --> collection[]

id:author:title:category:qty:price:delivery:schedule
22:Enid Mary Blyton:Oui-Oui et la Carte au trésor:ENFANTS:12:3.56:15/12/2022:"5:24"
13:Zitrou:Ducobu plouf:BD:113:8.56:15/12/2022:"12:30"
0:Enid Mary Blyton:Oui-Oui et Madame Ouistiti:ENFANTS:6:4.57:27/07/2022:"01:00"

....

Public Struct AVar
  'DType 4 int 9 str 7 float 8 Date/Time 12 variant
  'Data As Array
  ColumnKey As String
  Order As Integer
  A As Array
  AT As Integer 'type Array
End Struct

Public Struct Order
  Elem[4] As Struct AVar
End Struct

Private SK As New Order 'Sort Order by ColumnKey

Public Sub Main()

Dim t As Collection[]
System.Language = "fr_FR.utf8"  'useful for date[]

With SK.Elem[0]
  .ColumnKey = "category"
  .AT = 9
  .Order = gb.Descent
End With

With SK.Elem[1]
  .ColumnKey = "author"
  .AT = 9
End With

With SK.Elem[2]
  .ColumnKey = "qty"
  .AT = 4
  .Order = gb.Descent
End With

With SK.Elem[3]
  .ColumnKey = "delivery"
  .AT = 8
End With

t = SortByType4(3, "commandes.csv")  ' 0->3
'CheckHorizontal(t)
'Check(t)
SaveCsv("/tmp/foo.csv", t)

'old syntax SortByType("commandes.csv", 9, "author", 7, "price", 9, "title")
'old syntax SortByType2("commandes.csv")
End

Public Function Csv2Ac(FileCsv As String) As Collection[]
  Dim t As New Collection[], c As CsvFile
  c = New CsvFile(FileCsv, ":")
  'ok c = CsvFile.Open(FileCsv, ",")
  While Not c.Eof
  t.Add(c.Read())
  Wend
  Return t
End

Public Function SaveCsv(FileCsv As String, tb As Collection[])
Print "SaveCsv"
  Dim g As Collection
  Dim c As CsvFile
  c = CsvFile.Create(FileCsv, ",")
  g = tb[0]
  c.Fields = g.keys
  For i As Integer = 0 To tb.Max
    g = tb[i]
    'For Each item As Variant In g
    '  Print g.key, ":", item
    'Next
    c.Write(g)
  Next
  c.Close()

End

Private Sub InitA(k As Integer, table As Collection[])
'Initialize & populate SK, k is skIndex
Dim tmp As Object, g As Collection
If k > 3 Then Error.Raise("InitA: 0,1,2,3 only")
If Not SK.Elem[k].AT Then Error.Raise("InitA: DataType ??")
'Dim k As Integer = 0

 Select Case SK.Elem[k].AT
 Case 1
  tmp = New Boolean[]
  Print "DIM 1"
 Case 4
   tmp = New Integer[]
   Print "DIM 4"
 Case 9
   tmp = New String[]
   Print "DIM 9"
 Case 7
   tmp = New Float[]
   Print "DIM 7"
 Case 8
   tmp = New Date[]
   Print "DIM 8"
   ' TypeDate= date,date+time,time
 Default
   tmp = New String[]
   Print "DIM ELSE"
 End Select
 Print "typeOf tmp", TypeOf(tmp), "SK.Typeof", SK.Elem[k].AT, "K", k

  For i As Integer = 0 To table.max
    g = table[i]
    If g.Exist(SK.Elem[k].ColumnKey) Then
      If SK.Elem[k].AT = 8 Then
        tmp.Add(Val(g[SK.Elem[k].ColumnKey]))
      Else
        tmp.Add(g[SK.Elem[k].ColumnKey])

      Endif
    Endif
  Next
  If Not SK.Elem[k].Order Then SK.Elem[k].Order = gb.Ascent
  SK.Elem[k].A = tmp
  Debug "check SK.Elem[k].A.Max", k, SK.Elem[k].A.Max

End
Public Function SortByType4(Deep As Integer, FileCsv As String) As Collection[]
 If Deep > 3 Then Error.Raise("Sort:Deep:0,1,2,3max")
 Dim table As Collection[], k As Integer = 0, skIndex As Integer = 0

 table = Csv2Ac(FileCsv)

 Repeat
  InitA(skIndex, table)
  If skIndex = 0 Then
      For i As Integer = 0 To (SK.Elem[k].A.Max - 1)
        For j As Integer = i + 1 To SK.Elem[k].A.Max
          If SK.Elem[k].Order = gb.Ascent Then
            If SK.Elem[k].A[i] > SK.Elem[k].A[j] Then
              Print "0++\t\tswap", SK.Elem[k].A[i], SK.Elem[k].A[j]
              Swap SK.Elem[k].A[i], SK.Elem[k].A[j]
              Swap table[i], table[j]
            Endif
          Endif
          If SK.Elem[k].Order = gb.Descent Then
            If SK.Elem[k].A[i] < SK.Elem[k].A[j] Then
              Print "0--\t\tswap", SK.Elem[k].A[i], SK.Elem[k].A[j]
              Swap SK.Elem[k].A[i], SK.Elem[k].A[j]
              Swap table[i], table[j]
            Endif
          Endif
        Next
      Next
      'If sk = Deep Then Return table
  Endif

  If skIndex = 1 Then
      For i As Integer = 0 To (SK.Elem[k].A.Max - 1)
        For j As Integer = i + 1 To SK.Elem[k].A.Max

         If SK.Elem[k].A[i] = SK.Elem[k].A[j] Then
           Debug "====", SK.Elem[k].A[i], SK.Elem[k].A[j]
             If SK.Elem[k + 1].Order = gb.Ascent Then
               If SK.Elem[k + 1].A[i] > SK.Elem[k + 1].A[j] Then
Print "1++\t\tswap", SK.Elem[k + 1].A[i], SK.Elem[k + 1].A[j]
                 Swap SK.Elem[k + 1].A[i], SK.Elem[k + 1].A[j]
                 Swap table[i], table[j]
               Endif
             Endif
             If SK.Elem[k + 1].Order = gb.Descent Then
               If SK.Elem[k + 1].A[i] < SK.Elem[k + 1].A[j] Then
Print "1--\t\tswap", SK.Elem[k + 1].A[i], SK.Elem[k + 1].A[j]
                 Swap SK.Elem[k + 1].A[i], SK.Elem[k + 1].A[j]
                 Swap table[i], table[j]
               Endif
             Endif
          Endif
        Next
      Next
      'If sk = Deep Then Return table
  Endif

  If skIndex = 2 Then
      For i As Integer = 0 To (SK.Elem[k].A.Max - 1)
        For j As Integer = i + 1 To SK.Elem[k].A.Max

If (SK.Elem[k].A[i] = SK.Elem[k].A[j]) And (SK.Elem[k + 1].A[i] = SK.Elem[k + 1].A[j]) Then Debug "====", SK.Elem[k].A[i], SK.Elem[k].A[j], SK.Elem[k + 1].A[i], SK.Elem[k + 1].A[j]
             If SK.Elem[k + 2].Order = gb.Ascent Then
               If SK.Elem[k + 2].A[i] > SK.Elem[k + 2].A[j] Then
Print "2++\t\tswap", SK.Elem[k + 2].A[i], SK.Elem[k + 2].A[j]
                 Swap SK.Elem[k + 2].A[i], SK.Elem[k + 2].A[j]
                 Swap table[i], table[j]
               Endif
             Endif
             If SK.Elem[k + 2].Order = gb.Descent Then
               If SK.Elem[k + 2].A[i] < SK.Elem[k + 2].A[j] Then
Print "2--\t\tswap", SK.Elem[k + 2].A[i], SK.Elem[k + 2].A[j]
                 Swap SK.Elem[k + 2].A[i], SK.Elem[k + 2].A[j]
                 Swap table[i], table[j]
               Endif
             Endif
          Endif
        Next
      Next
      'If sk = Deep Then Return table
  Endif

  If skIndex = 3 Then
      For i As Integer = 0 To (SK.Elem[k].A.Max - 1)
       For j As Integer = i + 1 To SK.Elem[k].A.Max

If (SK.Elem[k].A[i] = SK.Elem[k].A[j]) And (SK.Elem[k + 1].A[i] = SK.Elem[k + 1].A[j]) And (SK.Elem[k + 2].A[i] = SK.Elem[k + 2].A[j]) Then Debug "====", SK.Elem[k].A[i], SK.Elem[k].A[j], SK.Elem[k + 1].A[i], SK.Elem[k + 1].A[j], SK.Elem[k + 2].A[i], SK.Elem[k + 2].A[j]
            If SK.Elem[k + 3].Order = gb.Ascent Then
              If SK.Elem[k + 3].A[i] > SK.Elem[k + 3].A[j] Then
Print "3++\t\tswap", SK.Elem[k + 3].A[i], SK.Elem[k + 3].A[j]
                Swap SK.Elem[k + 3].A[i], SK.Elem[k + 3].A[j]
                Swap table[i], table[j]
              Endif
            Endif
            If SK.Elem[k + 3].Order = gb.Descent Then
              If SK.Elem[k + 3].A[i] < SK.Elem[k + 3].A[j] Then
Print "3--\t\tswap", SK.Elem[k + 3].A[i], SK.Elem[k + 3].A[j]
                Swap SK.Elem[k + 3].A[i], SK.Elem[k + 3].A[j]
                Swap table[i], table[j]
              Endif
            Endif
         Endif
       Next
      Next
      'If sk = Deep Then Return table
  Endif
  If skIndex = Deep Then Return table
  Inc skIndex
  'Print "skIndex", skIndex
 Until skIndex > Deep
End


Le 17/01/2026 à 17:07, Gianluigi a écrit :
Il 17/01/26 16:15, Benoît Minisini ha scritto:
Le 17/01/2026 à 15:19, Gianluigi a écrit :
Il 17/01/26 14:48, Benoît Minisini ha scritto:
No. As I explaines, the order comes from a specific feature added to the hash table. This feature is not mandatory for a hash table to be a hash table. I added it because it allows to use the hash table both as a hash table and a rudimentory ordered list. But it has a cost: 16 bytes by element!

Hi Benoit,

I apologize, but as I told Jussi, I'm working on another job and I didn't explain myself well. Let me put it this way: if someone asks me if the Gambas3 collections are in order and I say yes, am I wrong?

No. It's just that it is not "officially" guaranteed yet, even if I won't change that now, and if I want an unordered Collection, I will create another class.

I'm ignorant, I haven't studied math, and I don't know hash tables, so I can't talk about them.

This is not math, this is algorithms.

A hash table is an array.

But to be able to use indexes that are strings for storing an element, the string is transformed (we say "hashed", hence the name "hash table") into an integer lower than the size of the array, that is the index in that array where we want to store the element.

Then, as two strings may lead to the same index, we actually store another array in each element of the initial array. It's that second- level array that stores all elements of the hash table whose string key lead to same index.

Then things become a bit complex, because when you add more elements to the hash table (or remove them), it adapts the size of its first-level array and reorganizes everything so that there is not too many string keys leading to the same index, for performance reasons.

I don't know if it's clear for you. You will find for sure better explanations on the Internet with good examples.

Regards,


Dear Benoit,

great, I finally figured out what these damn hash tables are.
Now I can confess, I'd read about them several times, and I never understood anything. You were really kind to clarify things for me; I never understood what collisions meant.
I swore to myself I'd never bother you again, but now I'm glad I did.

I can't tell you I love you because I already made that declaration to Fabien Bodard, but now my heart is undecided. 😍 🙂

Thanks again and best regards
Gianluigi




Follow-Ups:
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHBrian G <brian@xxxxxxxxxxxxxxxx>
References:
Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHBB <adamnt42@xxxxxxxxx>
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHBrian G <brian@xxxxxxxxxxxxxxxx>
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHBenoît Minisini <benoit.minisini@xxxxxxxxxxxxxxxx>
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHBrian G <brian@xxxxxxxxxxxxxxxx>
Re: Looping through an array with FOR EACHJussi Lahtinen <jussi.lahtinen@xxxxxxxxx>
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHJussi Lahtinen <jussi.lahtinen@xxxxxxxxx>
Re: Looping through an array with FOR EACHBrian G <brian@xxxxxxxxxxxxxxxx>
Re: Looping through an array with FOR EACHBenoît Minisini <benoit.minisini@xxxxxxxxxxxxxxxx>
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHBenoît Minisini <benoit.minisini@xxxxxxxxxxxxxxxx>
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>
Re: Looping through an array with FOR EACHBenoît Minisini <benoit.minisini@xxxxxxxxxxxxxxxx>
Re: Looping through an array with FOR EACHGianluigi <gradobag@xxxxxxxxxxx>