I wrote a macro sorter in the VIP section but I don't mind sharing here...
Someone was asking for an array sorter in slack the other day, so I wrote a fairly reusable array sorting include.
The way this is written is meant to allow for different types of arrays, and different types of comparers. Meaning, if you want to write a new compare sub and pass it in to do reverse alphabetical order, you can. Or you could write a comparer that works with int arrays, etc. This include also modifies the array in place without creating a duplicate array.
Of note, the Big-O runtime of this is lousy at O(n^2), but every time I've tested this it's been sub-second, so I don't think it matters for a macro.
Hack:
Also I noticed that when doing string.Compare[], if the string is surrounded by quotes it will always result in a negative comparison. This is probably a bug with core. To work around it, I strip away quotation marks (or anything that's a symbol) from the leading and trailing positions on the string. Any tips to make this cleaner I'd like to learn about.
SortArray.inc
Code: Select all
#warning
sub SortArray(String unsortedArrayName, String compareSubName)
/declare i int local
/declare j int local
/declare temp string local
/for i 1 to ${Math.Calc[${${unsortedArrayName}.Size} - 1]}
/for j ${Math.Calc[${i} + 1]} to ${${unsortedArrayName}.Size}
/if (${${compareSubName}[${${unsortedArrayName}[${i}]}, ${${unsortedArrayName}[${j}]}]}) {
/varset temp ${${unsortedArrayName}[${i}]}
/varset ${unsortedArrayName}[${i}] ${${unsortedArrayName}[${j}]}
/varset ${unsortedArrayName}[${j}] ${temp}
}
/next j
/next i
/return
sub AlphabeticalStringComparer(String a, string b)
/varset a ${TrimStringQuotes[${a}]}
/varset b ${TrimStringQuotes[${b}]}
/if (${b.Length} == 0) /return FALSE
/if (${a.Length} == 0) /return TRUE
/return (${a.Compare[${b}]} > 0)
sub TrimStringQuotes(String str)
/if (${str.Left[1].Compare[a]} < 0) /varset str ${str.Right[${Math.Calc[${str.Length} - 1]}]}
/if (${str.Right[1].Compare[a]} < 0) /varset str ${str.Left[${Math.Calc[${str.Length} - 1]}]}
/return ${str}
sub PrintArray(String arrayName)
/declare index int local
/for index 1 to ${${arrayName}.Size}
/echo ${${arrayName}[${index}]}
/next index
/return
Test Macro:
Code: Select all
#warning
#include SortArray.inc
sub main
| Populate array
/declare StringArray[10] string outer
/varset StringArray[1] "Jennifer"
/varset StringArray[2] Becky
/varset StringArray[3] Claire
/varset StringArray[4] "Michelle"
| Skip 5
/varset StringArray[6] "Sarah"
/varset StringArray[7] Althea
/varset StringArray[8] Maggie
| Skip 9, 10
/echo Time: ${Time}
/call SortArray "StringArray" "AlphabeticalStringComparer"
/echo Time2: ${Time}
/call PrintArray "StringArray"
| Expected: Althea, Becky, Claire, "Jennifer", Maggie, "Michelle", "Sarah", "", "", ""
/return