Android Question [solved] Strang list problem

JDS

Active Member
Licensed User
Longtime User
I've got a list defined in Starter Service Process_Globals (and yes it is initialized)

B4X:
Sub Process_Globals
 
 
    Public arZendingen As List

This list is filled with items of a type:
B4X:
Type TZending (zendingid As String, _
        vrachtnr As String, _
Zendingregels As List)

I've made a copy of the arZendingen list to another list -> arZnd
Now I want to add the Zendingregels of all items from arZnd to the first item of arZnd.

The code below doesn't fail, it works however at the "<--MARK" -line happens something strange. Yes tRegel is added to tZend2.Zendingregels. But at the same moment the same item in com.arZendingen is updated also.

B4X:
    Dim tZend As TZending : tZend.initialize
    Dim tSort As TZending : tSort.initialize
    iSize = arZnd.Size-1
    Dim y As Int
    For i = 0 To iSize
        If i>iSize Then Exit
        If i=0 Then
            Dim tZend As TZending : tZend.Initialize
            tZend=arZnd.Get(i)
            y=i
        Else
            Dim tSort2 As TZending : tSort2.Initialize
            tSort2=arZnd.Get(i)
            If tSort2.customer<>tZend.customerThen
                Dim tZend As TZending : tZend.Initialize
                tZend=tSort
                y=1
            Else
                For j = 0 To tSort2.Zendingregels.Size-1
                    Dim tRegel As TRegel : tRegel.initialize
                    tRegel=tSort2.Zendingregels.Get(j)
                    tZend.Zendingregels.Add(tRegel) '<--MARK
                        
                Next
                arZnd.RemoveAt(i)
                arZnd.RemoveAt(y)
                arZnd.InsertAt(y,tZend)
                i=i-1
                iSize=iSize-1
            End If
        End If
    Next

Am I missing something? Any thoughts?
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
Upload a small project which shows the issue.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
This is a mistake:
B4X:
  Dim tRegel As TRegel : tRegel.initialize
   tRegel=tSort2.Zendingregels.Get(j)
There is no reason to initialize the object if you are assigning a different one to the same variable.

Correct code:
B4X:
Dim tRegel As TRegel = tSort2.Zendingregels.Get(j)

Yes tRegel is added to tZend2.Zendingregels. But at the same moment the same item in com.arZendingen is updated also.
"Copying" the objects from one list to another doesn't create a new copy of the objects. The lists only hold references to the objects and the references are copied.
 
Upvote 0

emexes

Expert
Licensed User
I'm betting it is something to do with two object variables pointing to the same object.

edit: Erel's explanation is probably better.

I'm a bit doubtful about using a For loop that requires an additional loop variable test ie the loop limit is changing, and also where the loop variable is reversed/decremented inside the loop.

Code like that usually works better as a while loop.

Yes, you'll need an extra line of code to increment the loop variable, but at the same time, you'll save at least one line by not having the same loop test twice, and might even save another if you don't have to decrement it.
 
Last edited:
Upvote 0

JDS

Active Member
Licensed User
Longtime User
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.
    Dim arZendingen As List
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 TRegel (Eenheid As String, oms As String)
  
    Type TZending (zendingid As String, customer As Int, Zendingregels 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")
  
    arZendingen.initialize
  
    For i = 0 To 9
        Dim tZnd As TZending : tZnd.initialize
        tZnd.zendingid=i+1000
        tZnd.Zendingregels.Initialize
        If i<4 Then
            tZnd.customer = 10
        Else
            tZnd.customer = 2
        End If
        For j = 0 To 4
            Dim tReg As TRegel : tReg.initialize
            tReg.Eenheid="Eenheid "&j
            tReg.oms    ="Omschrijving "&(j+1000)
            tZnd.Zendingregels.Add(tReg)
        Next
        arZendingen.Add(tZnd)
    Next
  
  
End Sub

Sub Activity_Resume
  
    Dim iZnd As Int
    Dim tZend As TZending : tZend.initialize
    Dim llist As List : llist.initialize
    For i = 0 To arZendingen.Size-1
        tZend=arZendingen.Get(i)
        If tZend.customer < 10 Then
            llist.Add(tZend.zendingid)
        End If
      
    Next
  
    Createlist(llist)
  
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Createlist(llist As List)
    Dim tZend As TZending : tZend.initialize
    Dim tSort As TZending : tSort.initialize
    Dim iZnd, iFound, iSize As Int
    Dim arZnd As List : arZnd.initialize
  
    For i = 0 To arZendingen.Size-1
        tZend=arZendingen.Get(i)
        For j = 0 To llist.Size-1
            iZnd=llist.Get(j)
            If iZnd=tZend.zendingid Then
                If arZnd.Size=0 Then
                    arZnd.Add(tZend)
                Else
                    iFound=0
                    For x = 0 To arZnd.Size-1
                        tSort=arZnd.Get(x)
                        If tSort.customer=tZend.customer Then
                            arZnd.InsertAt(x+1,tZend)
                            iFound=1
                            Exit
                        End If
                    Next
                    If (iFound=0) Then arZnd.Add(tZend)
                End If
              
                Exit
            End If
        Next
    Next
  
  
    Dim tZend As TZending : tZend.initialize
    Dim tSort As TZending : tSort.initialize
    iSize = arZnd.Size-1
    Dim y As Int
    For i = 0 To iSize
        If i>iSize Then Exit
        If i=0 Then
            Dim tZend As TZending : tZend.Initialize
            tZend=arZnd.Get(i)
            y=i
        Else
            Dim tSort2 As TZending : tSort2.Initialize
            tSort2=arZnd.Get(i)
            If tSort2.customer<>tZend.customer Then
                Dim tZend As TZending : tZend.Initialize
                tZend=tSort
                y=1
            Else
                For j = 0 To tSort2.Zendingregels.Size-1
                    Dim tRegel As TRegel =tSort2.Zendingregels.Get(j)
                    tZend.Zendingregels.Add(tRegel) '<--MARK - in this example item 3 of arzendingen has 30 zendingregels but this should be 5
                  
                Next
                arZnd.RemoveAt(i)
                arZnd.RemoveAt(y)
                arZnd.InsertAt(y,tZend)
                i=i-1
                iSize=iSize-1
            End If
        End If
    Next
  
    Log("Done")
End Sub
 
Last edited:
Upvote 0

JDS

Active Member
Licensed User
Longtime User
This is a mistake:
B4X:
  Dim tRegel As TRegel : tRegel.initialize
   tRegel=tSort2.Zendingregels.Get(j)
There is no reason to initialize the object if you are assigning a different one to the same variable.

Correct code:
B4X:
Dim tRegel As TRegel = tSort2.Zendingregels.Get(j)


"Copying" the objects from one list to another doesn't create a new copy of the objects. The lists only hold references to the objects and the references are copied.

How can I create a copy a copy of a list? Without holding the references?
 
Upvote 0

JDS

Active Member
Licensed User
Longtime User
I've changed the example of post #5 with Erels suggestions but the problem persists.
 
Upvote 0

emexes

Expert
Licensed User
hang on, we have these three fields "zendingid", "vrachtnr", "Zendingregels" in the type:
B4X:
Type TZending (zendingid As String, _
        vrachtnr As String, _
Zendingregels As List)
but then we have another field "Verlader" here:
B4X:
Dim tSort2 As TZending : tSort2.Initialize
tSort2=arZnd.Get(i)
If tSort2.Verlader<>tZend.Verlader Then
How does that work? Or is there some auto-translation happening that is mucking up words that aren't Dutch or English?
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
It looks like you want to sort the arZnd List by one of the subfields. Is this correct? If so, which subfield?
 
Upvote 0

JDS

Active Member
Licensed User
Longtime User
hang on, we have these three fields "zendingid", "vrachtnr", "Zendingregels" in the type:
B4X:
Type TZending (zendingid As String, _
        vrachtnr As String, _
Zendingregels As List)
but then we have another field "Verlader" here:
B4X:
Dim tSort2 As TZending : tSort2.Initialize
tSort2=arZnd.Get(i)
If tSort2.Verlader<>tZend.Verlader Then
How does that work? Or is there some auto-translation happening that is mucking up words that aren't german or english?
Changed. Originally it was "verlader" (=dutch) but changed it to "customer" for the English speaking users.
 
Upvote 0

JDS

Active Member
Licensed User
Longtime User
It looks like you want to sort the arZnd List by one of the subfields. Is this correct? If so, which subfield?

I want to merge al "Zendingregels" of one customer to one "Tzending". Futher on in the programm I'll create a PDF document where the "Zendingregels" are printed.
This way I want to prevent looping al the items searching for the same customer when printing.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I've changed the example of post #5 with Erels suggestions but the problem persists.
My suggestion was not related to that problem.

The problems happens because you are not making copies of the type.

You can use this sub to make copies:
B4X:
Sub DuplicateType (obj As Object) As Object
   Dim ser As B4XSerializator 'RandomAccessFile library
   Return ser.ConvertBytesToObject(ser.ConvertObjectToBytes(obj))
End Sub
 
Upvote 0
Top