Re: Sorting?
Re: Sorting?
- Subject: Re: Sorting?
- From: "Arthur J. Knapp" <email@hidden>
- Date: Thu, 12 Sep 2002 13:48:55 -0400
>
Date: 12 Sep 2002 10:18:18 +0200
>
From: =?iso-8859-1?Q?G=F6ran_Ehn?= <email@hidden>
>
Subject: Sorting?
>
Does anyone have a sorting routine that sorts name/numbers correctly?
>
>
I used the sorting routine at
>
http://www.apple.com/applescript/guidebook/sbrt/pgs/sbrt.05.htm
>
but it gives me this:
>
page1_box0
>
page1_box1
>
page1_box10
>
page1_box11
>
page1_box12
>
page1_box13
>
page1_box14
>
page1_box15
>
page1_box16
>
page1_box17
>
page1_box18
>
page1_box19
>
page1_box2
>
page1_box20
>
page1_box21
>
page1_box22
Length Warning, (sorry):
set oldDelims to text item delimiters -- save
set pageBoxRefs to "page1_box1
page1_box10
page1_box11
page1_box12
page1_box13
page1_box14
page1_box15
page1_box16
page1_box17
page1_box18
page1_box19
page1_box2
page1_box20
page1_box21
page1_box22"
(* Break the string at every 'run' of numbers, (it is more
* effiecent to do this with the whole string, rather than
* iterate over each "page1_box##" line):
*)
set preSortRefs to NumberSplit(pageBoxRefs, false)
--
--> { "page", "1", "_box", "1", etc... }
(* Back to string, so we can get the lines:
*)
set numberSentinal to ASCII character 1
set text item delimiters to numberSentinal
set preSortRefs to preSortRefs as string
(* We want to get each paragraph, but first we want another
* sentinal to be inserted for where the paragraphs are,
* later on this will allow us to quickly re-stringify:
*)
set preSortRefs to every paragraph of preSortRefs
set paraSentinal to ASCII character 2
set text item delimiters to paraSentinal & return
set preSortRefs to every paragraph of (preSortRefs as string)
--
--> { "page`1`_box`1`~", "page`1`_box`10`~" }
(* Make each item "sort-ready":
*)
set text item delimiters to numberSentinal
repeat with i from 1 to preSortRefs's length
set preSortRefs's item i to preSortRefs's item i's text items
(* Coerce each 'number', (even items are numbers):
*)
repeat with j from 2 to preSortRefs's item i's length by 2
set preSortRefs's item i's item j to
(preSortRefs's item i's item j) as integer
end repeat
end repeat
--
--> {{"page", 1, "_box", 1, ""}, {"page", 1, "_box", 10, ""}, ...
(* Sort
*)
CustomQuickSort(preSortRefs, 1, preSortRefs's length, ListCompare)
set sortedRefs to preSortRefs
--
--> {{"page", 1, "_box", 1, ""}, {"page", 1, "_box", 2, ""}, ...
(* Back to strings, then to paragraphs:
*)
set text item delimiters to ""
set sortedRefs to sortedRefs as string
set text item delimiters to paraSentinal
set sortedRefs to sortedRefs's text items
set text item delimiters to oldDelims -- restore
(* All done
*)
sortedRefs --> {"page1_box1", "page1_box2", "page1_box10", ...
on ListCompare(a, b)
script q -- Serge object
property qa : a
property qb : b
end script
set alen to a's length
set blen to b's length
set i to 1
repeat until (i > alen) or (i > blen)
-- Test each item at (i)
--
if (q's qa's item i < q's qb's item i) then
return -1
else if (q's qa's item i > q's qb's item i) then
return 1
else
set i to i + 1
end if
end repeat
-- If we are here, then all items were equal up to
-- a certain point. So now it comes down to length:
--
return alen - blen
end ListCompare
on CustomQuickSort(a, l, r, custom_compare)
(*
* Sorts "in-place":
*)
local i, j, v --> SD debugging
(* Much thanks to Serge Belleudy-d'Espinose for that
* extra surge of speed. :)
*)
script o
property p : a
end script
script c
on comp(a, b)
if (a < b) then
return -1
else if (a > b) then
return 1
else
return 0
end if
end comp
end script
if (custom_compare's class as string = "handler") then
set c's comp to custom_compare
else if (custom_compare's class = script) then
set c to custom_compare
end if
set i to l
set j to r
set v to o's p's item ((l + r) div 2)
repeat while (j > i)
repeat while c's comp(o's p's item i, v) < 0
set i to i + 1
end repeat
repeat while c's comp(o's p's item j, v) > 0
set j to j - 1
end repeat
if (not i > j) then
(* set { i, j } to { j, i }
*)
set o_s_p_s_item_i to o's p's item i
set o's p's item i to o's p's item j
set o's p's item j to o_s_p_s_item_i
set i to i + 1
set j to j - 1
end if
end repeat
if (l < j) then CustomQuickSort(o's p, l, j, c)
if (r > i) then CustomQuickSort(o's p, i, r, c)
end CustomQuickSort
(* Break a string at every 'run' of digits.
*)
on NumberSplit(s, force_coercion)
set o to text item delimiters -- save
set c to ASCII character 1 -- sentinal
repeat with i from 0 to 9
set text item delimiters to i as string
set s to s's text items
set text item delimiters to c & i & c
set s to s as string
end repeat
set text item delimiters to c & c
set s to s's text items
set text item delimiters to ""
set s to s as string
set text item delimiters to c
set s to s's text items
set text item delimiters to o -- restore
if (force_coercion = true) then
-- even items are 'numbers'
--
repeat with i from 2 to s's length by 2
set s's item i to s's item i as integer
end repeat
end if
return s
end NumberSplit
{ 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.