I just noticed that the new to fw7 method
roAssociativeArray.keys() "returns an array containing the associative array keys in
lexicographical order" and a little lightbulb went in my head :idea: - this can be exploited to sort a list of objects!
Say you have list of objects like
songs = [
{title: “Without You”, artist: "Harry Nilsson", memeURL: "https://www.youtube.com/watch?v=aNN9nL2vppM", album:"Heinz's Wiener Stampede", ...},
{title: "Ken Lee", artist: "Valentina Hasan", memeURL: "http://knowyourmeme.com/memes/ken-lee", ...},
...
]
and want it sorted based on the title field. No problem - just use the function from below;
sorted(songs, "title") should return a new array sorted by the title field.
function sorted(arr as Object, keyName as String):
if getInterface(arr, "ifArray") = invalid then STOP
dict = { }
for each item in arr:
key = item[keyName] : if key = invalid then key = ""
val = dict[key]
if val = invalid then dict[key] = [item] else val.push(item)
end for
res = [ ]
for each key in dict.keys(): '<- sort magic happens here
res.append(dict[key])
end for
return res
end function
- Note i was so vainglorious (new word!) as to type the function above without testing it, so there might be bugs. Baring typos, it should work though.
- It should sort fine lists containing elements with duplicate keys (e.g. multiple songs with the same title). Moreover it should preserve the original order of such elements. Hence it should be able to sort by multiple keys - through repeatedly sorting, from least important to most important key (e.g. sorted(sorted(songs, "artist"), "title") )
- It can sort other collections beyond roArray - for example roByteArray, roList and roXMLList, since they'll all pass the getInterface(arr, "ifArray") sanity test. Still, it will return the sorted result as roArray. Passing roAssociativeArray should fail though, that's intentional since the result on that would have been unexpected (keys only) due to "for each" behavior.
- It's easy to write a version with the 2nd param being keyFunction, which instead of key = item[keyName] will do key = keyFunction(item) - e.g. for purposes of composite keys or hack-numeric sort. I actually started writing "universal" fn which would check getInterface(key, "ifString") vs getInterface(key, "ifFunction") but dropped it for brevity.
- There have been other sort functions published elsewhere, say implementing quicksort or shellsort in BrS proper. I wonder how they fare speed-wise to this one (which exploits the .keys() sort)?