Get unique list from array

jeffnooch

Member
Licensed User
Longtime User
What i'm currently doing is
1) adding data to an array
2) adding a log() entry that will print the value of the array during the loop (currently 2 dimensions but i could get away with 1 dimension if it is easier)
3) copying and pasting the data from the log into excel where i run an advanced filter to extract all unique values then calculate what % each value is of the total (ie sum of all unique value %'s should add to 100%)...

is there an easy way to accomplish #3 directly inside of B4A.
i don't know a good way to get a list of unique values from an array

any thoughts would be great...thanks in advance
 

stevel05

Expert
Licensed User
Longtime User
If I understand what you are trying to do correctly, you could add each value to a map as a key (the value could be anything), duplicates will be overwritten by the same key, leaving just unique keys. That could do it for you.
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Try something like

B4X:
Dim MyArray(10) As Int = Array As Int (99,25,13,25,95,13,11,8,15,99)
Dim MyMap As Map
Dim MyList As List
MyMap.Initialize
MyList.Initialize

For Each Item As Int In MyArray
   MyMap.Put(Item,"")
Next

For i = 0 To MyMap.Size-1
   MyList.Add(MyMap.GetKeyAt(i))
Next


MyList.Sort(True)

For Each Item As Int In MyList
   Log(Item)
Next

Log(MyList.Size&" Unique Entries")
 
Upvote 0

jeffnooch

Member
Licensed User
Longtime User
Steve,
ok...i tested that and that gives me a list of unique values as intended...thanks...

Now onto my second part...

let's say my array includes A,B,C,A,C,A,A

your code would return
A
B
C

is there a way to get it to return the counts and % for each (and preferably sorted decending on %)...something like:

A | 4 | 57.14%
C | 2 | 28.57%
B | 1 | 14.29%

thanks for your help
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Try This

B4X:
Dim MyArray(6) As Int = Array As Int (99,13,99,13,99,15,99)
Dim MyMap As Map
Dim NumberOfItems, ItemTotal As Int

MyMap.Initialize

For Each Item As Int In MyArray
    'Use the Value of the map stored in the key to count the items
   MyMap.Put(Item,MyMap.GetDefault(Item,0)+1)
Next

NumberOfItems = MyArray.Length
For i = 0 To MyMap.Size-1
   Item=MyMap.GetKeyAt(i)
   ItemTotal=MyMap.Get(Item)
   Log(Item&" "&ItemTotal&" "&NumberFormat((ItemTotal*100)/NumberOfItems,2,2)&"%")
Next
 
Upvote 0

jeffnooch

Member
Licensed User
Longtime User
Steve...works great...only thing it doesn't do is the sort...but i can live without that...

thanks for your help....i'll have to take a look at MAP and see what other things i might be able to use it for...
 
Upvote 0

jeffnooch

Member
Licensed User
Longtime User
great...if you can figure it out then post it here and i'll test it out with my data...
if not no worries...i'm in a much better place than using copy/paste into excel...
thanks again
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Try this one:

B4X:
Sub Process_Globals
     Type OutputType(Item As Int,Count As Int,Result As Float)
End Sub

Sub Activity_Create(FirstTime As Boolean)
'Working code .......
Dim MyArray(6) As Int = Array As Int (99,13,99,13,99,15,99)
Dim MyMap As Map
Dim NumberOfItems As Int
Dim MyList As List

MyMap.Initialize
MyList.Initialize

For Each Item As Int In MyArray
    'Use the Value stored in the map under the key to count the items
   MyMap.Put(Item,MyMap.GetDefault(Item,0)+1)
Next

NumberOfItems = MyArray.Length
For Each Key As Int In MyMap.Keys
    Dim R As OutputType
    R.Item=Key
    R.Count=MyMap.Get(Key)
    R.Result=(R.Count*100)/NumberOfItems
    MyList.Add(R)
Next

MyList.SortType("Result",False)

For Each R As OutputType In MyList
   Log(R.Item&" "&R.Count&" "&NumberFormat(R.Result,2,2)&"%")
Next
End Sub

Edit: I learnt something new too, not used sort type before, but will from now on!
 
Last edited:
Upvote 0

jeffnooch

Member
Licensed User
Longtime User
Steve...that's absolutely spot on...

quick question
so by using TYPE that essentially let's you treat a list like a 2 dimension array? ...can you pull out a specific entry...i'm thinking something like R.Item(3) so essentially that would be equivalent to something like myArray (0,3)? is that right? if so that'll definitely come in handy

thanks for all your help...i greatly appreciate it...plus i learned a few new things i'm sure i'll be able to apply to other projects...
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
You're welcome.

That's almost right, the list is a list of objects, in our case the objects are instances of a Type we have defined.

To access the data within the instance we have to assign the object in the list to an object of the correct type. So again in our case:

B4X:
Dim R As OutputType = MyList.Get(0)

Would assign the first item in the list to an object of the correct type.

Then we can access the data:

B4X:
R.Item = nn etc.

It would be the same if the list contained Buttons.

B4X:
Dim Btn As Button = MyBtnList.Get(0)

Btn.Text = "Click Here"

The
B4X:
For Each R As OutputType In MyList


Next
assigns each item in the list to R in turn for us.

We have the added benefit using List member SortType to be able to sort the list by any field that is contained in the type, and by ascending or descending.
 
Last edited:
Upvote 0

jeffnooch

Member
Licensed User
Longtime User
i think i'm following...i'll play around with it and see what i can do with it...

thanks again for your help
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…