Re: Sorting?
Re: Sorting?
- Subject: Re: Sorting?
- From: "Arthur J. Knapp" <email@hidden>
- Date: Fri, 13 Sep 2002 10:24:19 -0400
>
Date: Thu, 12 Sep 2002 13:48:55 -0400
>
Subject: Re: Sorting?
>
From: "Arthur J. Knapp" <email@hidden>
>
> Does anyone have a sorting routine that sorts name/numbers correctly?
>
set oldDelims to text item delimiters -- save
[snip]
Here is a handlerized version of the script I posted yesterday.
It internally uses the CustomQuickSort() and ListCompare() handlers
from my last posting, which I won't resend here.
set a to {"abc1def", "abc10def", "abc2def", "abc20def"}
set b to AlphaNumericSorted(a)
--> {"abc1def", "abc2def", "abc10def", "abc20def"}
on AlphaNumericSorted(a)
(*
* a == list of strings to sort
*
* --> returns list of strings, with 'numbers' sorted
* numerically.
*)
set oldDelims to text item delimiters -- save
copy a to a -- don't data share with passed parameter
(*
* Usually, I like to create my sort routines to work
* "in place", but given the "pre-digesting" of the
* list that I am using, it is easier simply to return
* a new list.
*)
--ie: { "abc1def", "abc10def", "abc2def", "abc20def" }
(* We want to perform mass-processing on all items at
* once, so we use an item-delimiter to keep the
* original items apart, and a runs-delimiter that
* goes before and after 'runs' of digits.
*)
set itemSentinal to ASCII character 1 --ie: "~"
set runsSentinal to ASCII character 2 --ie: "`"
(* Coerce to one string, makes the number-spliting
* much faster.
*)
set text item delimiters to itemSentinal
set a to a as string
--ie: "abc1def~abc10def~abc2def~abc20def"
(* Break the string at 'runs' of digits
*)
repeat with i from 0 to 9
--ie: i = 0
set text item delimiters to (i as string)
set a to a's text items
--ie: { "abc1def~abc1", "def~abc2def~abc2", "def" }
set text item delimiters to runsSentinal & i & runsSentinal
set a to a as string
--ie: "abc1def~abc1`0`def~abc2def~abc2`0`def"
end repeat
--ie: "abc`1`def~abc`1``0`def~abc`2`def~abc`2``0`def"
(* Now all digits have a sentinal before and after,
* so to obtain 'runs', we simply remove all adjacent
* sentinals.
*)
set text item delimiters to runsSentinal & runsSentinal
set a to a's text items
--ie: { "abc`1`def~abc`1", "0`def~abc`2`def~abc`2", "0`def" }
set text item delimiters to ""
set a to a as string
--ie: "abc`1`def~abc`10`def~abc`2`def~abc`20`def"
(* Having finished our mass-processing, we go back to
* individual items. By keeping an itemSentinal at the end
* of each item, we can perform a faster re-stringify
* later on.
*)
set text item delimiters to itemSentinal
set a to a's text items
--ie: { "abc`1`def", "abc`10`def", "abc`2`def", "abc`20`def" }
set text item delimiters to itemSentinal & runsSentinal & runsSentinal
set a to (a as string) & itemSentinal
--ie: "abc`1`def~``abc`10`def~``abc`2`def~``abc`20`def~"
set text item delimiters to runsSentinal & runsSentinal
set a to a's text items
--ie: { "abc`1`def~", "abc`10`def~", "abc`2`def~", "abc`20`def~" }
(* Now our processing will be more or less item-by-item.
*)
script o -- Serge object
property p : a
end script
(* Each item now needs to be list-ified, and split at
* the numbers.
*)
set text item delimiters to runsSentinal
repeat with i from 1 to a's length
--ie: "abc`1`def~"
set o's p's item i to o's p's item i's text items
--ie: { "abc", "1", "def~" }
(* The 'numbers' are at even indexes. We explicitly
* coerce them to integers so the sorting routine
* can use normal comparison operators.
*)
repeat with j from 2 to o's p's item i's length by 2
set o's p's item i's item j to ,
(o's p's item i's item j) as integer
end repeat
--ie: { "abc", 1, "def~" }
end repeat
--ie: { { "abc", 1, "def~" }, { "abc", 10, "def~" },
-- { "abc", 2, "def~" }, { "abc", 20, "def~" }
-- }
(* Sort, passing the custom sort ListCompare handler.
*
* NOTE: These are the same handlers I posted in my
* last email.
*)
my CustomQuickSort(a, 1, a's length, my ListCompare)
--ie: { { "abc", 1, "def~" }, { "abc", 2, "def~" },
-- { "abc", 10, "def~" }, { "abc", 20, "def~" }
-- }
(* Back to list of strings:
*)
set text item delimiters to ""
set a to a as string
--ie: "abc1def~abc2def~abc10def~abc20def~"
set text item delimiters to itemSentinal
set a to a's text items
--ie: { "abc1def", "abc2def", "abc10def", "abc20def", "" }
set text item delimiters to oldDelims
return a's items 1 thru -2
end AlphaNumericSorted
{ Arthur J. Knapp, of <
http://www.STELLARViSIONs.com>
a r t h u r @ s t e l l a r v i s i o n s . c o m
}
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.