max() function over arrays, single and multidimensional
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
max() function over arrays, single and multidimensional
Working with arrays, I've become aware of a need to find a max value and return the key corresponding to that value.
Firstly, is there a way (well, apart from what I've already done, getting the max value from the array and then looping through the keys to see if the corresponding value matches the found max) to return the key of the max array value?
Secondly, what's the best approach to finding the max value in the second tier (or potentially further, to make this a generic case) of a multidimensional array?
Such as:
theArray[1]["name"] ="John"
theArray[1]["age"] = 15
theArray[2]["name"] ="Paul"
theArray[2]["age"] = 21
theArray[3]["name"] ="George"
theArray[3]["age"] = 19
theArray[4]["name"] ="Ringo"
theArray[4]["age"] = 18
How would you recommend I get the key 2 from the max age? Any suggestions gratefully received.
Firstly, is there a way (well, apart from what I've already done, getting the max value from the array and then looping through the keys to see if the corresponding value matches the found max) to return the key of the max array value?
Secondly, what's the best approach to finding the max value in the second tier (or potentially further, to make this a generic case) of a multidimensional array?
Such as:
theArray[1]["name"] ="John"
theArray[1]["age"] = 15
theArray[2]["name"] ="Paul"
theArray[2]["age"] = 21
theArray[3]["name"] ="George"
theArray[3]["age"] = 19
theArray[4]["name"] ="Ringo"
theArray[4]["age"] = 18
How would you recommend I get the key 2 from the max age? Any suggestions gratefully received.
-
- Posts: 179
- Joined: Sat Apr 08, 2006 11:08 pm
- Contact:
Here's a recursive function that should work (I haven't tested it)
Best,
Mark
Code: Select all
function arrayMax pArray, pMax
repeat for each key k in pArray
if pArray[k] is an array then
put arrayMax(pArray[k], pMax) into pMax
else
if pArray[k] is a number then put max(pArray[k], pMax) into pMax
end if
end repeat
return pMax
end arrayMax
Mark
-
- Posts: 179
- Joined: Sat Apr 08, 2006 11:08 pm
- Contact:
Thanks Mark.
It's nifty using recursion but this walks the whole array/subarrays and gets the max from any key in the subarray. (It also barfs because of having a SQL datetimestamp in there, but I could trap for that.)
What I'm really looking for the (top level) key to be returned for the key for which a known subkey can be tested for the max value. As in the pseudo data above, I'd like a function that looks at the ["age"] subkey and finds the max of 21, thereby returning 2 as the top level key. I can then get the name for key 2 being returned as "Paul" (as well as the other associated data in other keys).
So far I have made functions that walk down two dimensions as:This works if I call the routines correctly with the right parameters, by calling to return the max value first and then get the key, but I was hoping for something more elegant. I'm surprised I'm having such a difficulty with it - with RunRev the problem is usually just picking which of the many ways to handle it.
Edit:
It's nifty using recursion but this walks the whole array/subarrays and gets the max from any key in the subarray. (It also barfs because of having a SQL datetimestamp in there, but I could trap for that.)
What I'm really looking for the (top level) key to be returned for the key for which a known subkey can be tested for the max value. As in the pseudo data above, I'd like a function that looks at the ["age"] subkey and finds the max of 21, thereby returning 2 as the top level key. I can then get the name for key 2 being returned as "Paul" (as well as the other associated data in other keys).
So far I have made functions that walk down two dimensions as:
Code: Select all
function fnGetKeyFromArrayValue pArray, pValue, pMultiKey
-- pass the array to walk, the value to search for (in this case the max of the "age" key that was returned from the other function beforehand, and the key name that is to be searched.
local tKey
if pArray is not an array then
return "Error: not an array"
else if pValue is empty then
return "Error: no search value supplied"
else if pMultiKey is not empty then
put fnGetSubArray(pArray, pMultiKey) into pArray
end if
if pArray begins with "Error" then
return pArray
else
repeat for each line tKey in the keys of pArray
if pArray[tKey] is pValue then
return tKey
end if
end repeat
end if
return "No matching value found"
end fnGetKeyFromArrayValue
function fnGetSubArray pArray, pMultiKey
local tKey, tArray
if pArray is not an array then
put "Error: not an array" into tArray
else if pMultiKey is empty then
put "Error: no subkey value supplied" into tArray
else
repeat for each line tKey in the keys of pArray
put pArray[tKey][pMultiKey] into tArray[tKey]
end repeat
end if
return tArray
end fnGetSubArray
Code: Select all
put max(fnGetSubArray(theArrayA,"age")) into theMaxAge
put fnGetKeyFromArrayValue(theArrayA, theMaxAge, "age") into theMaxKey
Edit:
Yes, thanks, sorry cross posted.Mark Smith wrote:Scratch that! I just re-read the question - you want the key of the max value...hmmm...
-
- Posts: 179
- Joined: Sat Apr 08, 2006 11:08 pm
- Contact:
Well, I've come up with this, which may help or not:
so the flattenArray function returns a list like:
1,name,paul
1,age,21
2,name,george
etc...
Which looks like it might be usable in this case.
Cheers,
Mark
Code: Select all
on mouseUp
put "paul" into tArray[1]["name"]
put 21 into tArray[1]["age"]
put "george" into tArray[2]["name"]
put 19 into tArray[2]["age"]
put "john" into tArray[3]["name"]
put 20 into tArray[3]["age"]
put "ringo" into tArray[4]["name"]
put 18 into tArray[4]["age"]
put flattenArray(tArray) into tList
sort lines of tList numeric descending by item -1 of each
put tList
end mouseUp
function flattenArray pArray
repeat for each key k in pArray
if pArray[k] is an array then
put flattenArray(pArray[k]) into tTempList
repeat for each line L in tTempList
put k & comma & L & cr after tList
end repeat
else
put k & comma & pArray[k] & cr after tList
end if
end repeat
return tList
end flattenArray
1,name,paul
1,age,21
2,name,george
etc...
Which looks like it might be usable in this case.
Cheers,
Mark
Very nice, thanks very much Mark. Adding a needle match on the key means I can return a simple filtered list of the values for the key concerned, making it easy to sort and get the max, as in:That's much appreciated, thanks again Mark.
Code: Select all
function flattenArray pArray, pNeedleKey
repeat for each key k in pArray
if pArray[k] is an array then
put flattenArray(pArray[k],pNeedleKey) into tTempList
repeat for each line L in tTempList
put k & comma & L & cr after tList
end repeat
else
if k is pNeedleKey then
put k & comma & pArray[k] & cr after tList
end if
end if
end repeat
return tList
end flattenArray
So I can put flattenArray(tArray,"age")
on mouseUp
put "paul" into tArray[1]["name"]
put 21 into tArray[1]["age"]
put "george" into tArray[2]["name"]
put 19 into tArray[2]["age"]
put "john" into tArray[3]["name"]
put 20 into tArray[3]["age"]
put "ringo" into tArray[4]["name"]
put 18 into tArray[4]["age"]
put flattenArray(tArray,"age") into tList
sort lines of tList numeric descending by item -1 of each
put item 1 of line 1 of tList into theKeyNeeded
put theKeyNeeded -- returns 1, as tArray[1]["age"] holds 21 which is the max.
end mouseUp
-
- Posts: 179
- Joined: Sat Apr 08, 2006 11:08 pm
- Contact:
Yes - I'm still a bit surprised that it was "a little challenge" though - I've got so used to finding a neat way of getting something out of Rev's built in stuff that I was convinced it was just me being stupid and missing a function that was just waiting for me to use. Walking the array seems a bit unnatural (albeit obvious that I should, in hindsight).