• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Sort a List with Integers & Letters
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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

  • Follow-Ups:
    • Re: Sort a List with Integers & Letters
      • From: "Nigel Garvey" <email@hidden>
  • Prev by Date: Re: File Path as URL question
  • Next by Date: Fwd: Odd AS user account problem...
  • Previous by thread: Re: Sort a List with Integers & Letters ( Reverse Speed Results When Using TEXT)
  • Next by thread: Re: Sort a List with Integers & Letters
  • Index(es):
    • Date
    • Thread