Intelligent sorting: NEW WINNER Dick Kriesel

FlexibleLearning admin at FlexibleLearning.com
Thu Jul 8 16:45:49 EDT 2010


This solution from Dick Kriesel is more accurate than any other solution so
far (to an unliminted depth for all practical purposes) and its speed is
comparable with the best to date. Yes it is long, but the demands for an
accurate intelligent sort require some heavy duty parsing. Breaking each
lines into sub-components is indeed the way to go, optimised by 'for each'.
The solution is clearly annotated and sorting by the parallel array keys of
each line is, in my view, a stroke of genius. The only, and quite
understandable, limitation that I can determine is special-formatted
sub-components such as dateTime, but within the parameters of the sample
data expectations it excels. Well done, Dick.

Save this somewhere like the Scripter's Scrapbook for when you need it. As
always, watch out for line-wraps...

function sortMe tData
  sort_a1a tData
  return tData
end sortMe

command sort_a1a @tData, tSortDelimiter, tOrigin -- note: sort tData
respecting chunks of digits
  --| By Dick Kriesel [dick.kriesel at mail.com]
  local tCharPrev, tDigits, tNonDigits, tSortKey, tSortKeys
  if tSortDelimiter is empty then
    put numToChar(8) into tSortDelimiter
  end if
  if tOrigin is empty then
    put 1000000 into tOrigin
    -- note: tOrigin = 1000000 enables alphabetic sorting for positive
integers up to 9,999,999
    -- note: the caller can enable sorting larger numbers, or can reduce the
number of characters that will be sorted
  end if

  /*
  Step through tData, separating chunks of digits from chunks of other
characters.
  For each character that's an integer, append it to a variable that holds
only digits.
  For each character that's not an integer, append it to a variable that
holds no digits.
  When a character is an integer, but the previous character wasn't, append
the string of
  non-digits to the line's sort key.
  When a character is not an integer, but the previous character was, add
the origin to the
  string of digits and append the sum to the line's sort key.
  */

  repeat for each line tLine in tData
    put empty into tCharPrev
    put empty into tDigits -- note: tDigits tracks the most recent digits
    put empty into tNonDigits -- note: tNonDigits tracks the most recent
characters other than digits
    put empty into tSortKey

    repeat for each char tChar in tLine
      if tChar is an integer then
        if tCharPrev is an integer then
          put tChar after tDigits
        else
          put tChar into tDigits
          if tNonDigits is not empty then
            put tNonDigits & tSortDelimiter after tSortKey
            put empty into tNonDigits
          end if
        end if
      else
        if tCharPrev is an integer then
          put tChar into tNonDigits
          put tOrigin + tDigits & tSortDelimiter after tSortKey
          put empty into tDigits
        else
          put tChar after tNonDigits
        end if
      end if
      put tChar into tCharPrev
    end repeat

    if tDigits is not empty then
      put tOrigin + tDigits after tSortKey
    else if tNonDigits is not empty then
      put tNonDigits after tSortKey
    end if
    put tSortKey into tSortKeys[tLine]
  end repeat

  sort tData by tSortKeys[each]
end sort_a1a



Hugh Senior
FLCo




More information about the Use-livecode mailing list