Android Code Snippet [B4X][LOA] ListOfArrays with 1D data

ListOfArrays data structure can be useful even with single dimensional data.
LOA v0.96 adds a helper method for creating such LOAs:
B4X:
Dim colors As ListOfArrays = LOAUtils.CreateFrom1DList("Color", Array("red", "green", "blue"))
The header is optional. Pass empty string if not needed.

Another new method is ListOfArray.AddColumnWithValue. It adds a new column, filled with the same value.

We have an AI generated list of names:
B4X:
Dim Names() As String = Array As String( _
    "John", _
    "Emma", _
    "Michael", _
    "Olivia", _
    "Daniel", _
    "Sophia", _
    "James", _
    "Ava", _
    ...
)
    Dim AllNames As ListOfArrays = LOAUtils.CreateFrom1DList("Name", Names)

We want to split this list based on the names' lengths. LOASet, the iterator, is useful for such tasks:
B4X:
'collect the indices of all rows where the name length is shorter than or equal to 4:
Dim ls As LOASet = AllNames.CreateLOASet
Do While ls.NextRow
    If ls.GetValue(0).As(String).Length <= 4 Then ls.CollectIndex
Loop
'create two collections. One with the collected indices and another with the non-collected indices
Dim ShortNames As ListOfArrays = AllNames.GetRows(ls.CollectedValues)
Dim LongNames As ListOfArrays = AllNames.GetRows(AllNames.NegateRowsSelection(ls.CollectedValues))
Using the new AddColumnWithValue method, we add a new column that will store the lengths:
B4X:
AllNames.AddColumnWithValue("Length", 0)
Now we iterate over the rows and set the lengths:
B4X:
Dim ls As LOASet = AllNames.CreateLOASet
Do While ls.NextRow
    Dim Name As String = ls.GetValue("Name")
    'set the length value for each row
    ls.SetValue("Length", Name.Length)
Loop

We can sort the names based on the length column:
B4X:
AllNames.Sort("Length", True)
And get back a 1d list:
B4X:
Dim SortedNames As List = AllNames.GetColumn("Name")
Log(SortedNames)

Output:
Name (#rows=4, #cols=1)
-----------------------------
John
Emma
Ava
Mia
Name (#rows=16, #cols=1)
-----------------------------
Michael
Olivia
Daniel
Sophia
James
Name Length (#rows=20, #cols=2)
-----------------------------
Ava 3
Mia 3
John 4
Emma 4
James 5
(ArrayList) [Ava, Mia, John, Emma, James, Lucas, Henry, Ethan, Grace, Olivia, Daniel, Sophia, Amelia, Evelyn, Michael, William, Benjamin, Isabella, Charlotte, Alexander]


Project is attached.
 

Attachments

  • LOA_1d.zip
    13.5 KB · Views: 59
For added flexibility, it's good to add these two features (The creator Erel):
Like:
AddUniqeRow(NewRow() As Object,UniqColIndx As Object) As Boolean
InsertUniqeRow(NewRow() As Object,UniqColIndx As Object, RowIndx as int) As Boolean
if Success return True

I wrote down the routine AddUniqeRow routine and tested it.
.......Writing the InsertUniqeRow routine should be similar.
B4X:
Sub AddUniqeRow(table1 As ListOfArrays,NewRow_Array() As Object,UniqColIndx As Object) As Boolean
    Dim ColValue As Object =-1
    'If table1.Header.Length>0 Then
        If UniqColIndx Is String And table1.Header.Length>0 Then
            For i=0 To table1.Header.As(List).Size-1
                If table1.Header(i).As(String).ToUpperCase=UniqColIndx.As(String).ToUpperCase Then
                    UniqColIndx=i
                    Exit
                End If
            Next
        Else If IsNumber(UniqColIndx)=False Then
            Log("ColIndx is Wrong")
            Return False
        End If
        ColValue=NewRow_Array(UniqColIndx)
    'End If
    If table1.GetRowsByValue(UniqColIndx,ColValue).Size=0 Then
        table1.AddRow(NewRow_Array)
        Return True
    Else
        Dim res As String'="[" & IIf(table1.Header.Length>0, table1.Header(UniqColIndx),"ColNo (" &UniqColIndx) & ") = " & ColValue &  "]  is Found"
        If table1.Header.Length>0 Then
            res = table1.Header(UniqColIndx)
        Else   
            res="ColNo (" & UniqColIndx & ")"
        End If
        res=  res & "[" & ColValue &  "] = is Found" & Chr(13)& Chr(10) & "Can Not Added!"
        Log(res)
        ToastMessageShow(res,True)
        Return False
    End If
End Sub
 
Update for AddUniqeRow and InsertUniqeRow Routens :

Update:
Sub AddUniqeRow(table1 As ListOfArrays,NewRow_Array() As Object,UniqColIndx As Object) As Boolean
    Return AddInsUniqeRow(table1,NewRow_Array,UniqColIndx, -1)
End Sub

Sub InsertUniqeRow(table1 As ListOfArrays,NewRow_Array() As Object,UniqColIndx As Object, InsertRowIndx As Int)  As Boolean
    Return AddInsUniqeRow(table1,NewRow_Array,UniqColIndx, InsertRowIndx)
End Sub

Sub AddInsUniqeRow(table1 As ListOfArrays,NewRow_Array() As Object,UniqColIndx As Object, InsertRowIndx As Object) As Boolean
    If IsNumber(InsertRowIndx) Then
        If InsertRowIndx > table1.Size Then InsertRowIndx=-1
    Else
        InsertRowIndx=-1
    End If
    Dim ColValue As Object =-1
    If UniqColIndx Is String And table1.Header.Length>0 Then
        For i=0 To table1.Header.As(List).Size-1
            If table1.Header(i).As(String).ToUpperCase=UniqColIndx.As(String).ToUpperCase Then
                UniqColIndx=i
                Exit
            End If
        Next
    Else If IsNumber(UniqColIndx)=False Then
        Log("ColIndx is Wrong")
        Return False
    End If
    ColValue=NewRow_Array(UniqColIndx)
    If table1.GetRowsByValue(UniqColIndx,ColValue).Size=0 Then
        If InsertRowIndx>=0 Then
            table1.InsertRow(InsertRowIndx,NewRow_Array)
        Else
            table1.AddRow(NewRow_Array)
        End If
        Return True
    Else
        Dim res As String'="[" & IIf(table1.Header.Length>0, table1.Header(UniqColIndx),"ColNo (" &UniqColIndx) & ") = " & ColValue &  "]  is Found"
        If table1.Header.Length>0 Then
            res = table1.Header(UniqColIndx)
        Else
            res="ColNo (" & UniqColIndx & ")"
        End If
        res=  res & "[" & ColValue &  "] = is Found" & Chr(13)& Chr(10) & "Row Was Not " & IIf (InsertRowIndx>=0,"Inserted! at Index " & InsertRowIndx,"Added!")
        Log(res)
        ToastMessageShow(res,True)
        Return False
    End If
End Sub
 
Top