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
-
stam
- Posts: 3070
- Joined: Sun Jun 04, 2006 9:39 pm
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
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: 3070
- Joined: Sun Jun 04, 2006 9:39 pm
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
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
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
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
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: 3070
- Joined: Sun Jun 04, 2006 9:39 pm
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

- Posts: 119
- Joined: Thu Apr 13, 2006 6:25 pm
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: 3070
- Joined: Sun Jun 04, 2006 9:39 pm
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

- Posts: 4171
- Joined: Sun Jan 07, 2007 9:12 pm
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: 3070
- Joined: Sun Jun 04, 2006 9:39 pm
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...