Android Question Need help with structures

KKmac

Member
I have been using Visual Studio for 12+ years. This is my first go around with B4A. I can't seem to find the right answer for creating structures. For example, in Visual Studio

Structure PersonDefinition
Dim Name as String
Dim Address as String
Dim City as String
Dim Age as Integer
End Structure

Dim Person() as PersonDefinition

So I can have Person(0) as a person, Person(1) as a different person, etc.
Person(0).Name = "Kevin"or Person(1).Age = 30.
If I want to sort that array, I can create keys for the sorting by column, such as age.

The only way I found (so far) to create this structure in B4A is:

Dim PersonDefinition(Name as String, Address as String, City as String, Age as Int)
Dim Person() as PersonDefinition

If this is the right way, then how would I sort this by age, or alphabetically by name?

I found one place that said to put it in a list, then sort the list. I did that, and it worked, to a degree.
However, I couldn't just use MySortList(0).Name to get the info I need.

It's very clear to me that the terminology is vastly different for the same thing, such as in VS, they are Forms, where B4A is Pages.
I can't seem to locate the proper term for structures. I have read about arrays, collections, and maps. But they aren't very clear. I guess it's just not clicking yet.

Also, my example is shortened. In my "structure", I have far more declaration, such as First Name, Last Name, Address, City, State, Zip, Email, Phone, and so on.

While there are a number of coding similarities, this really isn't visual basic. At least not the one I know.

One more obstacle, My Person declaration itself is multi-array.

Dim Person(5, 20) as PersonDefinition

Kinda hard to explain why I am doing this. I have an event with contestants, and the first array represents each round of competition.
People get eliminated each round, so the second declaration (20) will decrease each round.

I need to be able to sort this mess. I could do this all day long in VS, but things are different here.
I almost never ask for help in a forum, but I am stumped.

Can anyone shed some light on what I have right, wrong, and what I should be doing instead.

Thanks
 

walt61

Active Member
Licensed User
Longtime User
This might get you started:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.

    ' A Type is like a Structure in VS; add as many members as needed; members can also be
    ' complex variables like Lists, Maps, Types, or views like Labels, Buttons, ...
    Type PersonDefinition(Name As String, Address As String, City As String, Age As Int)
    Dim PersonsList As List ' Forget arrays, use Lists ! You don't need to declare a dimension for Lists.

End Sub

Sub Activity_Create(FirstTime As Boolean)

    Dim i As Int
    Dim j As Int

    'Activity.LoadLayout("Layout")

    PersonsList.Initialize

    ' Create PersonsList with 5 items.
    ' You could also use a Map instead of a List; the Map's keys
    ' would be e.g. 1 through 5, and the values would be lists
    ' containing variables of type 'PersonDefinition'.
    For i = 0 To 4
        ' Initialise PersonsListSub
        Dim personsListSub As List
        personsListSub.Initialize
        ' Create PersonsListSub with 20 items
        For j = 0 To 19
            Dim person As PersonDefinition = CreatePersonDefinition(j, j, j, j) ' Pass the real values here
            personsListSub.add(person)
        Next
        ' Sort PersonsListSub by 'Name', case-insensitive
        personsListSub.SortTypeCaseInsensitive("Name", True)
        ' Alternatively, sort PersonsListSub by 'Age'
        'personsListSub.SortType("Age", True)
        ' Add PersonsListSub to PersonsList
        PersonsList.Add(personsListSub)
    Next

    ' Fetch the 'PersonsListSub' for the 2nd round
    Dim secondRound As List = PersonsList.Get(1) ' The first item has index zero

    ' Fetch the Persons from list 'SecondRound'
    For i = 0 To (secondRound.Size - 1)
        Dim onePerson As PersonDefinition = secondRound.Get(i)
        Log(i & ": " & onePerson.Name)
    Next

End Sub

' This sub is generated by hovering the mouse over PersonDefinition in
' sub Globals, and then clicking the "Generate 'Create Type' Sub" link.
Public Sub CreatePersonDefinition (Name As String, Address As String, City As String, Age As Int) As PersonDefinition

    Dim t1 As PersonDefinition
    t1.Initialize
    t1.Name = Name
    t1.Address = Address
    t1.City = City
    t1.Age = Age
    Return t1

End Sub
 
Last edited:
Upvote 0

aeric

Expert
Licensed User
Longtime User
Another option is to use my MinimaListUtils library.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I suggest you use a SQL database.
The above is absolutely the right choice, in your case.


I found one place that said to put it in a list, then sort the list. I did that, and it worked, to a degree.
However, I couldn't just use MySortList(0).Name to get the info I need.
MySortList.Get(Index).As([PersonType]).Name (where PersonType is your custom type, created with"Type PersonType(...))
or (better)
Dim Person As PersonType = MySortList.Get(Index)
Person.Name = ...
 
Upvote 0

KKmac

Member
Thank you all for your suggestions.

Walt61 and LucasMs both suggested the part I was missing. I got it to work.
I'm not good at SQLs but I will probably need to learn them.

For those curious, I am writing software for a beer tasting event that I run with my friends.
The app needs to be able to log all participants names and beer entries.
We score each beer in multiple categories and this app will add up the scores.
There is actually a lot going on with this (event and app).

Been doing this since 2016, with a Windows version of this software, but mobile is the way to go.

Thanks again for the very quick responses. It helped out a lot.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
B4X has a variety of ways of doing things.
The attached project works in B4J (desktop) and in B4A (android) - the code is the same.

You mentioned multiple groups of individuals, sorting, and more. I have created a very simple
demo to show how easy and natural it works in just 80 lines of code.

It is a B4XPages template, where in B4J pages are forms. In B4A pages are panels inside an activity.
Unzip the attached file and in the project folder run B4J or B4A.

(I zipped it by cntl clicking on third line in code below - I am explaining because you are new to this)
(when you post in this forum code use </> tags)

B4X:
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region

'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip

Sub Class_Globals
    Type Person(Group As Int, Name As String, Address As String, City As String, Age As Int)
    Private Root As B4XView    'ignore
    Private xui As XUI
    
    Private missing As Int = -1
End Sub

Public Sub Initialize
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Dim group(5) As List
    For i = 0 To 4
        group(i).Initialize        'now we can add individuals to each group list
    Next
    
    Dim names1() As String = Array As String("John", "Alice", "Anne", "Michael", "Gordon", "William") 'groups need not be the same size
    Dim names2() As String = Array As String("Alphonse", "Mark", "Louise", "Pamela")
    
    'add these persons to groups 0 and 1
    For Each pname As String In names1
        group(0).Add(CreatePerson(0, pname, "", "", missing))
    Next
    For Each pname As String In names2
        group(1).Add(CreatePerson(1, pname, "", "", missing))
    Next

    'sort each group() by name
    For i = 0 To 4
        group(i).SortType("Name", True)
    Next
    
    'index all individuals by name
    Dim ByName As Map
    ByName.Initialize
    For i = 0 To 4
        For j = 0 To group(i).Size - 1
            Dim indiv As Person = group(i).Get(j)
            ByName.Put(indiv.Name, indiv)        'this points to the same object as the one in the group list
        Next
    Next
    
    'Add age to a individual when it becomes available - note inline casting to Person
    ByName.Get("Anne").As(Person).Age = 22  'this changes not only the item in the map but also the item in the group list - they are the same
    
    'show group(0) individuals
    Log($"Name${TAB}Age${TAB}Group"$)
    Log(TAB)
    For Each indiv As Person In group(0)
        Log(indiv.Name & TAB & IIf(indiv.Age=missing, "-", indiv.age) & TAB & indiv.group)
    Next

'Log results(note that they are sorted and age is updated)

'Name    Age    Group
'
'Alice    -    0
'Anne    22    0
'Gordon    -    0
'John    -    0
'Michael    -    0
'William    -    0
End Sub

Public Sub CreatePerson (Group As Int, Name As String, Address As String, City As String, Age As Int) As Person
    Dim t1 As Person
    t1.Initialize
    t1.Group = Group
    t1.Name = Name
    t1.Address = Address
    t1.City = City
    t1.Age = Age
    Return t1
End Sub
 

Attachments

  • structures.zip
    14.3 KB · Views: 40
Upvote 0

Sabotto

Well-Known Member
Licensed User
B4X has a variety of ways of doing things.
The attached project works in B4J (desktop) and in B4A (android) - the code is the same.

...
I looked at your example. Well done
I would like to ask you for clarification on this line
B4X:
ByName.Get("Anne").As(Person).Age = 22  'this changes not only the item in the map but also the item in the group list - they are the same
Why is the change made in the Map also received by the List? Aren't they two separate objects? Can you explain it to me?
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

Sabotto

Well-Known Member
Licensed User
I think I understood (correct me if I'm wrong)
B4X:
ByName.Put(indiv.Name, indiv)        'this points to the same object as the one in the group list
the Person object is passed by reference so any changes made later in the Map always affect the same object which is always the same one present in the List
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Another option is to use my MinimaListUtils library.
I added an example:
https://www.b4x.com/android/forum/threads/b4x-web-minimalistutils.155724/#post-1002820
 
Upvote 0

KKmac

Member
I have another question. In visual studio, if I want to expand an array, I simply Redim Preserve Array(#)

There is no"Redim" or "Preserve" in B4A.
Whenever I Dim the array larger, I lose the data in the previous arrays. For Instance, If I have array(0) with data, then Dim Array(1), I lose the data in array(0)

As I stated, I am making software for an event, and the size of the array will vary, depending on how many people show up.
I don't want to have to define an array to a specific size. I should be able to expand as I need.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
I have another question. In visual studio, if I want to expand an array, I simply Redim Preserve Array(#)

There is no"Redim" or "Preserve" in B4A.
Whenever I Dim the array larger, I lose the data in the previous arrays. For Instance, If I have array(0) with data, then Dim Array(1), I lose the data in array(0)

As I stated, I am making software for an event, and the size of the array will vary, depending on how many people show up.
I don't want to have to define an array to a specific size. I should be able to expand as I need.
It's better to start a new thread for new questions.
My answer is use List.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Look at line 31 and 35 in post #8. With Lists, you can add, insertAt, removeAt, and more.
I don't know if you have already done this - but study the guides (it best to download all guides on the 'Learn' at the top of this Forum)
I go back to it quite often.

https://www.b4x.com/guides/B4XLanguage.html

B4X is not VB, it is better and it is cross-platform.
However, you do have to learn it like any other new computer language.
With patience, this could be an interesting experience.

As you have seen, the community is more than willing to help you.
 
Last edited:
Upvote 0

KKmac

Member
Thanks again.

I actually changed all of my arrays to lists, and everything is working (so far). I appreciate the input and suggestions.

LucaMs gave a link that showed the answer:

Dim Array(10) as Int
Array = RedimPreserve(Array, 15)

This will be good to know but I am working with lists now.
I have searched a lot and can never seem to find these answers so I greatly appreciate the insight.

I guess the term "Basic" when used in Visual Basic and Basic4Android do not mean the same thing.
I thought Basic4Android used the visual basic language (that I already know), with a compiler for Android. Not really!

Thanks again.
 
Upvote 0

MrKim

Well-Known Member
Licensed User
Longtime User
Thanks again.

I actually changed all of my arrays to lists, and everything is working (so far). I appreciate the input and suggestions.

LucaMs gave a link that showed the answer:

Dim Array(10) as Int
Array = RedimPreserve(Array, 15)

This will be good to know but I am working with lists now.
I have searched a lot and can never seem to find these answers so I greatly appreciate the insight.

I guess the term "Basic" when used in Visual Basic and Basic4Android do not mean the same thing.
I thought Basic4Android used the visual basic language (that I already know), with a compiler for Android. Not really!

Thanks again.
Don't be afraid to ask questions. The forum here is wonderful.
It IS different from VB because there are SO MANY MORE ways to skin the cat. With VB there is usually kind of 1 best way to do things. In B4X I can spend more time looking at all of the ways to do something than I spend actually writing the code to do it :p. Generally speaking you can find an example here for just about anything.
As for searching for answers here I have much better luck using google, typing B4X and then what I am searching for.
 
Upvote 0
Top