|
digitaljams Newbie
Joined: 02 Nov 2007 Posts: 9
|
Posted: Sun Jan 03, 2010 6:09 pm
How to sort intergers ASC or DESC |
Looking for a way to sort a listing of numbers in ASC or DESC fashion.
31
20620
594
14785
Currently the only way I am aware of to sort things is via the sort command.. but it doesnt work for comparing numbers.
List = {31|20620|594|14785}
#SORT list
#SHOW @list
This yields 14785|20620|31|594
Works great for strings.. not so well for intergers/numbers....
Suggestions? Thus far I have started working a very messy Switch statement that will do it.. but I would assume that there is a better simpler way. |
|
|
|
MattLofton GURU
Joined: 23 Dec 2000 Posts: 4834 Location: USA
|
Posted: Sun Jan 03, 2010 8:55 pm |
It's probably just as good to chop your list up into separate variables based on length, then apply the %sort() function to those variables, and finally connect them all together based on sort direction:
Code: |
#function @SortNumbers($list,$direction) {
#switch (%isnumber(%replace($list,"|","")) {
//numerical list
//19 digits is the maximum length of the 64-bit integers CMud can mathematically handle
#local $lengths $newlist
//initialize $lengths so we can tell what's used and not used after the sort
#loop 1,19 {
#addkey $lengths %i "NA"
}
//divide $list into $lengths
#forall $list {
#if ($lengths.%len(%i) = "") {#addkey $lengths %len(%i) %i} {#addkey $lengths %len(%i) %concat($lengths.%len(%i),"|",%i)}
}
//apply sort and construct the new list
#if ($direction) {
//descending order
#loop 19,1 {
#if ($lengths.%i != "NA") {
#if ($newlist = "") {$newlist = %sort($length.%i)} {$newlist = %concat($newlist,"|",%sort($length.%i))}
}
}
#return $newlist
} {
//ascending order
#loop 19,1 {
#if ($lengths.%i != "NA") {
#if ($newlist = "") {$newlist = %sort($length.%i)} {$newlist = %concat($newlist,"|",%sort($length.%i))}
}
}
#return $newlist
}
}
($list = "") {//no list}
(1) {//list is not numeric}
}
|
|
|
_________________ EDIT: I didn't like my old signature |
|
|
|
gamma_ray Magician
Joined: 17 Apr 2005 Posts: 496
|
Posted: Mon Jan 04, 2010 3:11 pm |
Code: |
<func name="quicksort" id="116">
<value>#local left,right,pivot,length
$length = %numitems($list)
#if ($length = 0) {
#return %null
} {
#if ($length = 1) {
#return {$list|}
} {
$length = $length/2
$pivot = $list.$length
$list = %delnitem($list, $length)
#if %begins($order,dec) {
#for $list {
#if (%i >= $pivot) {
$left = %additem(%i,$left)
} {
$right = %additem(%i,$right)
}
}
} {
#for $list {
#if (%i <= $pivot) {
$left = %additem(%i,$left)
} {
$right = %additem(%i,$right)
}
}
}
#return %concat(@quicksort($left,$order),$pivot,"|",@quicksort($right,$order))
}
}</value>
<arglist>list,order</arglist>
</func>
|
This is a quick implementation of a recursive quicksort (pretty much following the algorithm from Wikipedia). I couldn't come up with an elegant way of concating the pieces without getting extra pipe characters, so there's one extra (empty) item on the end of the list after the sort finishes. You can use delnitem to get rid of it. Usage would be something like
Code: |
var = @quicksort(@var,dec)
var = %delnitem(@var,%numitems(@var)) |
"dec" is optional, anything that does not start with "dec" will sort in increasing order. Oh, and it works on numbers ONLY. Attempting to sort non-numeric items will probably fail in amusing ways.
(I really wanted to do an in place quicksort, but CMud was having none of it.) |
|
|
|
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Mon Jan 04, 2010 6:00 pm |
This really should be implemented as a built in function. Something this basic shouldn't need to be reinvented by the end user.
|
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Mon Jan 04, 2010 7:56 pm |
Yes and Zugg has already put it on his to do list.
|
|
_________________ Taz :) |
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|