Re: Sort a List with Integers & Letters
Re: Sort a List with Integers & Letters
- Subject: Re: Sort a List with Integers & Letters
- From: "Nigel Garvey" <email@hidden>
- Date: Tue, 3 Apr 2007 23:58:10 +0100
Steven Valenti wrote on Tue, 3 Apr 2007 11:05:56 -0400:
>I'd like to work this out but I don't know much shell scripting. My
>actual code needs to sort a list of a list of records written to a
>database every time a new item is added.
>The list will look more like this with a lot more record properties...
>set theList to {{ModelNumber:"1610G", ModelName:"Gold Plate"},
>{ModelNumber:"121ZB", ModelName:"Zip Guard"}, {ModelNumber:"114",
>ModelName:"White Matte"}} & ¬
> {{ModelNumber:"13", ModelName:"Sterling Silver"},
>{ModelNumber:"21124", ModelName:"Blueberry"}, {ModelNumber:"121FB",
>ModelName:"Flat Bottom"}}
>I want to sort the list by the ModelNumber.
I suppose I could more usefully have posted a relevant, working script
earlier on instead of showing off my merge sort. The script below uses
the customisable version of Arthur's and my qsort, with a custom script
object that sorts lists in parallel, based on the ModelNumber of each
item. Since this has to work with pre-Tiger systems, without the 'numeric
strings' attribute, the list is duplicated and the ModelNumbers in the
duplicate are padded with leading zeros so that their leading numerics
are all 10 digits wide. (Add more zeros if necessary.) The duplicate is
then sorted and the sort moves are paralleled in the original. Not
pretty, but it works.
on CustomQsort(theList, l, r, compObj)
script o
property cutoff : 10
property p : theList
on qsrt(l, r)
set i to l
set j to r
set v to my p's item ((l + r) div 2)
repeat while (j > i)
set u to my p's item i
repeat while (compObj's isLess(u, v))
set i to i + 1
set u to my p's item i
end repeat
set w to my p's item j
repeat while (compObj's isGreater(w, v))
set j to j - 1
set w to my p's item j
end repeat
if (i > j) then
else
set my p's item i to w
set my p's item j to u
compObj's swap(i, j)
set i to i + 1
set j to j - 1
end if
end repeat
if (j - l < cutoff) then
else
qsrt(l, j)
end if
if (r - i < cutoff) then
else
qsrt(i, r)
end if
end qsrt
on isrt(l, r)
set x to l
set z to l + cutoff - 1
if (z > r) then set z to r
set v to my p's item x
repeat with y from (x + 1) to z
if (compObj's isLess(my p's item y, v)) then
set x to y
set v to my p's item y
end if
end repeat
tell my p's item l
set my p's item l to v
set my p's item x to it
end tell
compObj's swap(l, x)
set u to my p's item (l + 1)
repeat with i from (l + 2) to r
set v to my p's item i
if (compObj's isLess(v, u)) then
set my p's item i to u
repeat with j from (i - 2) to l by -1
if (compObj's isLess(v, my p's item j)) then
set my p's item (j + 1) to my p's item j
else
set my p's item (j + 1) to v
compObj's shift(j + 1, i)
exit repeat
end if
end repeat
else
set u to v
end if
end repeat
end isrt
end script
set listLen to (count theList)
if (listLen > 1) then
if (l < 0) then set l to listLen + l + 1
if (r < 0) then set r to listLen + r + 1
if (r = l) then
else
if (l > r) then
set temp to l
set l to r
set r to temp
end if
if (r - l < o's cutoff) then
else
o's qsrt(l, r)
end if
o's isrt(l, r)
end if
end if
return -- nothing
end CustomQsort
script sortOnModelNumber
property recordList : missing value
on isLess(a, b)
(a's ModelNumber < b's ModelNumber)
end isLess
on isGreater(a, b)
(a's ModelNumber > b's ModelNumber)
end isGreater
on swap(a, b)
tell item a of my recordList
set item a of my recordList to item b of my recordList
set item b of my recordList to it
end tell
end swap
on shift(a, b)
tell item b of my recordList
repeat with i from b - 1 to a by -1
set item (i + 1) of my recordList to item i of my recordList
end repeat
set item a of my recordList to it
end tell
end shift
end script
on convertNumStrings(thisList)
script o
property recordList : thisList
end script
set o's recordList to thisList
set digits to "0123456789"
set zeros to "0000000000"
set z to (count zeros)
considering case
repeat with i from 1 to (count thisList)
set mn to ModelNumber of item i of o's recordList
set c to (count mn)
repeat until (character c of mn is in digits)
set c to c - 1
end repeat
set ModelNumber of item i of o's recordList to text 1 thru (z -
c) of zeros & mn
end repeat
end considering
end convertNumStrings
set theList to {{ModelNumber:"1610G", ModelName:"Gold Plate"},
{ModelNumber:"121ZB", ModelName:"Zip Guard"}, {ModelNumber:"114",
ModelName:"White Matte"}} & ¬
{{ModelNumber:"13", ModelName:"Sterling Silver"},
{ModelNumber:"21124", ModelName:"Blueberry"}, {ModelNumber:"121FB",
ModelName:"Flat Bottom"}}
copy theList to list2
convertNumStrings(list2)
set sortOnModelNumber's recordList to theList
CustomQsort(list2, 1, -1, sortOnModelNumber)
theList
--> {{ModelNumber:"13", ModelName:"Sterling Silver"},
{ModelNumber:"114", ModelName:"White Matte"}, {ModelNumber:"121FB",
ModelName:"Flat Bottom"}, {ModelNumber:"121ZB", ModelName:"Zip Guard"},
{ModelNumber:"1610G", ModelName:"Gold Plate"}, {ModelNumber:"21124",
ModelName:"Blueberry"}}
NG
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden