[SOLVED] Filtering an array...

LiveCode is the premier environment for creating multi-platform solutions for all major operating systems - Windows, Mac OS X, Linux, the Web, Server environments and Mobile platforms. Brand new to LiveCode? Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

Post Reply
stam
Posts: 2680
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

[SOLVED] Filtering an array...

Post by stam » Sun Jul 19, 2020 4:19 am

Hi all,
have tried my best to search/read/experiment but can’t get this to work.

I have stored a database cursor as an array in a custom property of a data grid - call this ‘AllLines’ of data grid ‘datagrid’.
Works well for displaying all items, but i want be able to filter this, and would prefer not to continuously query the database unless needed.

I can’t seem to select out the array items i need however.

My code passes the text to filter on to a switch statement, but I’m obviously not doing it right… the command is:

Code: Select all

Command filterList pFilter
 switch pFilter
      case "All"
         set the dgData of group “datagrid” to (the AllLines of group "datagrid")
         break //THIS WORKS AS EXPECTED
         
      Case “xyz”
         put the AllLines of group "datagrid" into tArray
         repeat for each item tArr in tArray
            if tArr[“key”] = “xyz” then //key is the name of the field to compare with pFilter
               put tArr into tSelected
            end if
         end repeat

         set the dgData of group “datagrid” to tSelected //NOTHING HAPPENS
         break 
                  
 end switch
end command

Very grateful if someone can point me in the right direction…
Last edited by stam on Mon Jul 20, 2020 11:10 pm, edited 3 times in total.

cpuandnet
Posts: 32
Joined: Thu Jan 17, 2019 6:43 am

Re: Filtering an array...

Post by cpuandnet » Sun Jul 19, 2020 6:35 am

Hi Stam,

Change your repeat control structure to use element instead of item like this

Code: Select all

repeat for each element tArr in tArray
Item is used in chunk expressions with itemDelimiter. Key and element would be used in repeat control structures with arrays.

I hope that helps.

stam
Posts: 2680
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Filtering an array...

Post by stam » Sun Jul 19, 2020 10:51 am

Yes that did it, thank you.

I also discovered another minor issue - i've had to create a counter to (x = 0) so that i can assign an integer key to the array item being added, ie:

Code: Select all

...
put 0 into x
repeat for each element tArr in tArray
            if tArr[“key”] = “xyz” then //key is the name of the field to compare with pFilter
               put x + 1 into x
               put tArr into tSelected[x]
            end if
end repeat
...
unless there is a way to automatically append a collection of key:value pairs as an array item?
Without this i just ended up with tSelected containing the last array to be added

cpuandnet
Posts: 32
Joined: Thu Jan 17, 2019 6:43 am

Re: Filtering an array...

Post by cpuandnet » Mon Jul 20, 2020 6:08 am

I'm not aware of any methods that allow you to insert or delete elements of an array. The only other option is using a the number of elements expression as follows:

Code: Select all

repeat for each element tArr in tArray
            if tArr[“key”] = “xyz” then //key is the name of the field to compare with pFilter
               put tArr into tSelected[the number of elements of tSelected + 1]
            end if
end repeat
But, my preference is simplicity over elegance such as what you have used. It is often times easier to follow the logic when you have to make modifications later or getting new developers up to speed on your project.

AxWald
Posts: 578
Joined: Thu Mar 06, 2014 2:57 pm

Re: Filtering an array...

Post by AxWald » Mon Jul 20, 2020 11:08 am

Hi,

if you want to filter a simple array (key - value):

Code: Select all

   --  put "the original array" into myArray
   --  put "the value I search for" into myStrg
   repeat for each key K in myArray
      if myArray[K] = myStrg then put myArray[K] into newArray[K]
   end repeat
   return newArray
Now you have a copy of myArray in newArray that only contains the entries where the value matches myStrg.

If you have a nested array (each key contains a sub-array with named subKeys):

Code: Select all

   --  put "the original array" into myArray
   --  put "the name of the subkey" into myFld
   --  put "the value I search for" into myStrg
   repeat for each key K in myArray
      if myArray[K][myfld] = myStrg then put myArray[K] into newArray[K]
   end repeat
   return newArray
Same result. newArray contains only the matching sub-arrays.

If you want go further, check this:

Code: Select all

   --  put "the original array" into myArray
   --  put "the name of the subkey" into myFld
   --  put "begins with " & quote & "A" & quote into myStrg	  --  something wierd :)
   repeat for each key K in myArray
      put quote & myArray[K][myfld] & quote into myVar
      if value(myVar && myStrg) then put myArray[K] into newArray[K]
   end repeat
   return newArray
Have fun!
All code published by me here was created with Community Editions of LC (thus is GPLv3).
If you use it in closed source projects, or for the Apple AppStore, or with XCode
you'll violate some license terms - read your relevant EULAs & Licenses!

cpuandnet
Posts: 32
Joined: Thu Jan 17, 2019 6:43 am

Re: Filtering an array...

Post by cpuandnet » Mon Jul 20, 2020 4:08 pm

Even better. Thanks AxWald!

cpuandnet
Posts: 32
Joined: Thu Jan 17, 2019 6:43 am

Re: Filtering an array...

Post by cpuandnet » Mon Jul 20, 2020 8:05 pm

After thinking about it AxWald, i realized there might be a single case scenario where your suggestion might be a problem. If key K is numeric, which it is in Stam's case, then the new array would have numeric keys that were non-contiguous (i.e. 2,5,7 instead of 1,2,3). This would cause an issue if one was referencing the array directly ( i.e. tSelected[1][key] or tSelected[1]["abc"] ). If one was using a repeat control structure with the new array then it would work as expected.

For illustration purposes, executing the following routine

Code: Select all

   put "123" into tArray[1]["abc"]
   put "xyz" into tArray[2]["abc"]
   put "456" into tArray[3]["abc"]
   put "xyz" into tArray[4]["abc"]
   
   repeat for each key tKey in tArray
      if tArray[tKey]["abc"] = "xyz" then put tArray[tKey] into tSelected[tKey]
   end repeat
results in tSelected having non-contiguous numeric keys in the first dimension as follows.

tSelected[2]["abc"]
tSelected[4]["abc"]


Not really a problem if one is aware of that.

stam
Posts: 2680
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Filtering an array...

Post by stam » Mon Jul 20, 2020 11:10 pm

Thanks for the excellent suggestions everyone - positive experience with LiveCode so far in spite the simple but bewildering syntax lol.
Will be posting a few more questions going forward till i get the hang of it...

rkriesel
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 118
Joined: Thu Apr 13, 2006 6:25 pm

Re: Filtering an array...

Post by rkriesel » Tue Jul 21, 2020 12:44 am

cpuandnet wrote:
Mon Jul 20, 2020 8:05 pm
...

Code: Select all

   repeat for each key tKey in tArray
      if tArray[tKey]["abc"] = "xyz" then put tArray[tKey] into tSelected[tKey]
   end repeat
... results in tSelected having non-contiguous numeric keys in the first dimension ...
That can be shorter and faster without the repeat loop:

Code: Select all

   filter elements of tArray where each["abc"]="xyz" into tSelected
You see how "filter" can be your friend. See more about it in the dictionary.
-- Dick

stam
Posts: 2680
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: [SOLVED] Filtering an array...

Post by stam » Tue Jul 21, 2020 2:00 am

rkriesel wrote:
Tue Jul 21, 2020 12:44 am
filter elements of tArray where each["abc"]="xyz" into tSelected
Thanks Dick - that did look interesting so i gave it a try and after a few false starts got it to work.
I didn't realise you could refer to each [key] in this fashion!

Not sure if speed is noticeably different but certainly many fewer lines/more sustainable code.
Very helpful example indeed, thank you.

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3997
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: [SOLVED] Filtering an array...

Post by bn » Tue Jul 21, 2020 10:21 am

Thanks Dick for the "filter" variant.

@stam "filter" is faster than "for each key" in this case.

Code: Select all

on mouseUp
   put 1 into tCounter
   repeat 10000
      put "123" into tArray[tCounter]["abc"]
      add 1 to tCounter
      put "xyz" into tArray[tCounter]["abc"]
      add 1 to tCounter
      put "456" into tArray[tCounter]["abc"]
      add 1 to tCounter
      put "xyz" into tArray[tCounter]["abc"]
      add 1 to tCounter
   end repeat
   put  the milliseconds into tTime
   
   repeat for each key tKey in tArray
      if tArray[tKey]["abc"] = "xyz" then put tArray[tKey] into tOldSelected[tKey]
   end repeat
   
   put the milliseconds - tTime into t1
   put the milliseconds into tTime
   
   filter elements of tArray where each["abc"]="xyz" into tSelected
   
   put the milliseconds - tTime into t2
   
   put (the number of elements of tOldSelected) = (the number of elements of tSelected) into tEqual
   
   put "repeat each key:"  && t1 & ms & cr & "filter elements:" && t2 & ms
end mouseUp
put this into a button and the times will show up in the message box

Kind regards
Bernd

stam
Posts: 2680
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: [SOLVED] Filtering an array...

Post by stam » Tue Jul 21, 2020 11:38 am

bn wrote:
Tue Jul 21, 2020 10:21 am
@stam "filter" is faster than "for each key" in this case.
Sure, I get that. I meant to say that in my case, because the arrays are small, it isn’t noticeably quicker.

But I’d still go with the Filter method because the code is now much more readable/maintainable.
What was useful to learn was the syntax - while this definition is listed in the documentation, the examples given didn’t make this clear.
It was very helpful to see that:

Code: Select all

Filter element of tArray where  each [key]
is valid syntax - I’d always favour such an expression over a loop, for simplicity if nothing else...

Post Reply

Return to “Getting Started with LiveCode - Experienced Developers”