Extended list

This script combines some useful methods of AS3 Array with those of Lingo List. Moreover, some of the original Lingo list methods like add(), append(), deleteAt() and getAt() are modified. For example, getAt() method returns VOID instead of “index out of range” exception.

new( {…args} ) - Returns a new list, you can specify the initial values as arguments.
dispose() - Destroys the list
shuffle() - Shuffles the list values in-place, using Fisher – Yates algorithm.
add( {…args} )* - Adds values to a list. For a sorted list, the values are placed in their proper order.
getAt()* - Prevents “Index out of range” exception.
deleteAt()* - deleteAt()*
append( {…args} )* - Adds the specified values to the end of a list.
shift() - Removes the first element from an array and returns that element.
pop() - Removes the last element from a list and returns the value of that element.
unshift( …args ) - Adds one or more elements to the beginning of a list and returns the new count of the list.
slice( startIndex, endIndex ) - Returns a new list that consists of a range of elements from the original list, without modifying the original list.
splice( startIndex, deleteCount{, … values} ) - Adds elements to and removes elements from a list.
some( handler{, object} ) - Executes a test function on each item in the list until an item is reached that returns TRUE.
every( handler{, object} ) - Executes a test handler on each item in the list until an item is reached that returns FALSE for the specified handler.
filter( handler{, object} ) - Executes a test handler on each item in the list and constructs a new list for all items that return TRUE for the specified handler.
forEach( handler{, object} ) - Executes a handler on each item in the list.
map( handler{, object} ) - Executes a handler on each item in a list, and constructs a new list of items corresponding to the results of the handler on each item in the original list.
sortOn( intColumnIndex{, symbolOrder} ) - Sorts the list on given “column”.
concat() - Concatenates the elements specified in the parameters with the elements in a list and creates a new list.
reverse() - Reverses the list in-place.
join( separator ) - Returns a string, constructed by items in the list, with the separator inserted between them.
toString() - Returns a string that represents the elements in the specified list, separated by commas.
lastIndexOf( searchElement, startIndex ) - Searches for an item in a list, working backward from the last item, and returns the index position of the matching item.
typeOf() - Returns the name of the script as a symbol.
-- "Xlist" parent script
-- Author: Vladin M. Mitov
-- May, 2011
-- http://www.ed-multimedia.com

-- EXAMPLES:
------------------------------
-- myList = script( "xList" ).new( 1, 2, 3 )
-- put myList.interface()

-- myList.reverse()
-- put myList.toString()  -- "3,2,1"
-- myList.add( 4, 5, 6 )
-- put myList.toString()  -- "3,2,1,4,5,6"
-- myList.sort()
-- put myList.toString()  -- "1,2,3,4,5,6"

-- myList = script( "xList" ).new( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 )
-- put myList.filter( #getEven ).toString() -- "2,4,6,8,10"

-- A handler, defined in a movie script
--on getEven( aelement )
--  return( aelement mod 2 = 0 )
--end getEven

-------------------------------------------------
-- PROPERTIES
-------------------------------------------------
on ___________________________PROPERTIES
end
property ancestor

-------------------------------------------------
-- CONSTRUCTOR / DESTRUCTOR
-------------------------------------------------
on ___________________________CONSTRUCTOR_DESTRUCTOR
end
on new( me )
  ancestor = list()
  p = the paramCount
  repeat with i = 2 to p
    callAncestor( #add, me, param( i ) )
  end repeat
  return me
end new

on dispose( me )
  ancestor.deleteAll()
  ancestor = VOID
end dispose

-------------------------------------------------
-- PUBLIC METHODS
-------------------------------------------------
on ___________________________PUBLIC_METHODS
end

on getAt( me, n )
  if( n < 1 or n > count( ancestor ) ) then return VOID
  return ancestor[ n ]
end getAt

on deleteAt( me, n )
  if( n < 1 or n > count( ancestor ) ) then return VOID
  callAncestor( #deleteAt, me, n )
  return TRUE
end deleteAt

on lastIndexOf( me, searchElement, startIndex )
  if( voidP( startIndex ) ) then startIndex = count( ancestor )
  repeat with i = startIndex down to 1
    if( ancestor[ i ] =  searchElement ) then
      return i
    end if
  end repeat
  return VOID
end lastIndexOf

on add( me )
  p = the paramCount
  repeat with i = 2 to p
    callAncestor( #add, me, param( i ) )
  end repeat
end add

on addAt( me, pos, val )
  if( voidP( pos ) ) then return FALSE
  if( pos < 1  ) then return FALSE
  if( voidP( val ) ) then return FALSE
  callAncestor( #addAt, me, pos, val )
end addAt

on append( me )
  p = the paramCount
  repeat with i = 2 to p
    callAncestor( #append, me, param( i ) )
  end repeat
end append

on pop( me )
  n = callAncestor( #getLast, me )
  callAncestor( #deleteAt, me, count( ancestor ) )
  return n
end pop

on shift( me )
  e = callAncestor( #getAt, me, 1 )
  callAncestor( #deleteAt, me, 1 )
  return e
end shift

on unshift( me )
  p = the paramCount
  repeat with i = p down to 2
    callAncestor( #addAt, me, 1, param( i ) )
  end repeat
  return count( ancestor )
end unshift

on slice( me, startIndex, endIndex )
  retval = me.script.new()
  p = the paramCount
  if( voidP( startIndex ) ) then
    s = 1
    e = e = count( ancestor )
  end if
  if( p = 2 ) then
    if( startIndex = 1 or startIndex = 0 ) then
      s = 1
      e = count( ancestor )
    else if( startIndex < 0 ) then
      e = count( ancestor )
      s = startIndex + e + 1
    else if( startIndex > 0 ) then
      s = startIndex
      e = count( ancestor )
    end if
  else if( p = 3 ) then
    if( startIndex = 0 or endIndex = 0 ) then
      return retval
    else if( startIndex > 0 and endIndex < 0 ) then
      s = startIndex
      e = count( ancestor ) + endIndex + 1
    else if( startIndex < 0 and endIndex > 0 ) then
      return retval
    else if( startIndex > 0 and endIndex > 0 ) then
      if( startIndex = endIndex  ) then
        s = startIndex
        e = startIndex
      else if( startIndex > endIndex  ) then
        return retval
      else if( startIndex < endIndex  ) then
        s = startIndex
        e = endIndex
      end if
    else if( startIndex < 0 and endIndex < 0 ) then
      if( startIndex = endIndex  ) then
        s = count( ancestor ) + startIndex + 1
        e = s
      else if( startIndex > endIndex  ) then
        return retval
      else if( startIndex < endIndex  ) then
        s = count( ancestor ) + startIndex + 1
        e = count( ancestor ) + endIndex + 1
      end if
    end if
  end if
  repeat with i = s to e
    retval.add( ancestor[ i ] )
  end repeat
  return retval
end slice

on splice( me, startIndex, deleteCount, values )
  retval = me.script.new()
  p = the paramcount
  s = integer( startIndex )
  if( voidp( s ) or s = 0 ) then s = 1
  if( s < 0 ) then s = count( ancestor ) + s + 1
  if( p = 1 ) then
    return retval
  else if( p <= 2 ) then
    e = count( ancestor )
  else
    if( ilk( deleteCount ) <> #integer ) then deleteCount = 0
    e = min( count( ancestor ), s + deleteCount - 1 )
  end if
  repeat with i = e down to s
    retval.addAt( 1, ancestor[ i ] )
    callAncestor( #deleteAt, me, i )
  end repeat
  if( p < 4 ) then return retval
  repeat with j = p down to 4
    xparam = param( j )
    if( ilk( xparam ) = #list or ilk( xparam ) = #propList ) then
      cnt = count( xparam )
      repeat with jj = cnt down to 1
        callAncestor( #addAt, me, s, xparam[ jj ] )
      end repeat
    else
      callAncestor( #addAt, me, xparam )
    end if
  end repeat
  return retval
end splice

on some( me, ahandler, aobject )
  if( voidP( aobject ) ) then aobject = _movie
  cnt = count( ancestor )
  repeat with i = 1 to cnt
    element = ancestor[ i ]
    f = call( ahandler, aobject, element, i, me )
    if( f = TRUE ) then
      return f
    end if
  end repeat
  return FALSE
end some

on every( me, ahandler, aobject )
  if( voidP( aobject ) ) then aobject = _movie
  cnt = count( ancestor )
  repeat with i = 1 to cnt
    element = ancestor[ i ]
    f = call( ahandler, aobject, element )
    if( f = FALSE ) then
      return f
    end if
  end repeat
  return TRUE
end every

on filter( me, ahandler, aobject )
  if( voidP( aobject ) ) then aobject = _movie
  cnt = count( ancestor )
  retval = me.script.new()
  repeat with i = 1 to cnt
    element = ancestor[ i ]
    f = call( ahandler, aobject, element )
    if( f = TRUE ) then
      retval.append( element )
    end if
  end repeat
  return retval
end filter

on forEach( me, ahandler, aobject )
  if( voidP( aobject ) ) then aobject = _movie
  cnt = count( ancestor )
  repeat with i = cnt down to 1
    element = ancestor[ i ]
    f = call( ahandler, aobject, element, i, me )
  end repeat
end forEach

on map( me, ahandler, aobject )
  if( voidP( aobject ) ) then aobject = _movie
  cnt = count( ancestor )
  retval = me.script.new()
  repeat with i = 1 to cnt
    element = ancestor[ i ]
    retval.append( call( ahandler, aobject, element ) )
  end repeat
  return retval
end map

on shuffle( me )
  cnt = count( ancestor )
  if ( cnt = 0 ) then return FALSE
  repeat while ( cnt > 0 )
    j = random( cnt )
    tempi = ancestor[ cnt ]
    tempj = ancestor[ j ]
    ancestor[ cnt ] = tempj
    ancestor[ j ] = tempi
    cnt = cnt - 1
  end repeat
  return TRUE
end shuffle

on count( me )
  if( voidP( ancestor ) ) then return VOID
  return count( ancestor )
end count

on concat( me )
  p = the paramCount
  t = callAncestor( #duplicate, me )
  retval = me.script.new()
  repeat with i = 2 to p
    e = param( i )
    if( ilk( e ) = #list ) then
      cnt = count( e )
      repeat with j = 1 to cnt
        t.append( e[ j ] )
      end repeat
    else
      t.append( e )
    end if
  end repeat
  retval.ancestor = t
  return retval
end concat

on reverse( me )
  left = 1
  right = count( ancestor )
  repeat while( left < right )
    temp = ancestor[ left ]
    ancestor[ left ]  = ancestor[ right ]
    ancestor[ right ] = temp
    left = left + 1
    right = right - 1
  end repeat
end reverseList

on join( me, sep )
  t = EMPTY
  cnt = count( ancestor )
  repeat with i = 1 to cnt
    put ancestor[ i ] & sep after t
  end repeat
  len = t.length
  reallength = ( len - sep.length ) + 1
  repeat with j = len down to reallength
    delete t.char[ t.length ]
  end repeat
  return t
end join

on toString( me )
  t = me.join( "," )
  return t
end toString

on sortOn( me, columntoSortOn, order )
  if ( ilk( ancestor ) <> #list ) then return FALSE
  if ( count( ancestor ) = 0 ) then return FALSE
  if ( ilk( ancestor[1] ) <> #list ) then return FALSE
  if( voidP( order ) or [#ASC, #DESC].getPos( order ) = 0 ) then order = #ASC
  case( order ) of
    #ASC :__sort_on_internal_ASC( me, columntoSortOn )
    #DESC:__sort_on_internal_DESC( me, columntoSortOn )
  end case
end sortOn

on is( me, atype )
  obj = me
  types = [ #list, #xlist ]
  t = obj.typeOf()
  repeat while t <> #xlist
    types.append( t )
    obj = obj.getAprop( #ancestor )
    t = obj.typeOf()
  end repeat
  put types
  return( types.getPos( atype ) > 0 )
end is

on typeOf( me )
  the itemdelimiter = quote
  return symbol( string( me ).item[ 2 ] )
end typeOf

on interface( me )
  msg = EMPTY
  put "new( {...args} )                                -- Returns a new list, you can specify the initial values as arguments." & RETURN after msg
  put "dispose()                                       -- Destroys the list" & RETURN after msg
  put "shuffle()                                       -- Shuffles the list values in-place, using Fisher–Yates algorithm." & RETURN after msg
  put "add( {...args} )*                               -- Adds values to a list. For a sorted list, the values are placed in their proper order." & RETURN after msg
  put "getAt()*                                        -- Prevents "&quote&"Index out of range"&quote&" exception." & RETURN after msg
  put "deleteAt()*                                     -- Prevents "&quote&"Index out of range"&quote&" exception." & RETURN after msg
  put "append( {...args} )*                            -- Adds the specified values to the end of a list." & RETURN after msg
  put "shift()                                         -- Removes the first element from an array and returns that element." & RETURN after msg
  put "pop()                                           -- Removes the last element from a list and returns the value of that element." & RETURN after msg
  put "unshift( ...args )                              -- Adds one or more elements to the beginning of a list and returns the new count of the list." & RETURN after msg
  put "slice( startIndex, endIndex )                   -- Returns a new list that consists of a range of elements from the original list, without modifying the original list." & RETURN after msg
  put "splice( startIndex, deleteCount{, ... values} ) -- Adds elements to and removes elements from a list." & RETURN after msg
  put "some( handler{, object} )                       -- Executes a test function on each item in the list until an item is reached that returns TRUE." & RETURN after msg
  put "every( handler{, object} )                      -- Executes a test handler on each item in the list until an item is reached that returns FALSE for the specified handler." & RETURN after msg
  put "filter( handler{, object} )                     -- Executes a test handler on each item in the list and constructs a new list for all items that return TRUE for the specified handler." & RETURN after msg
  put "forEach( handler{, object} )                    -- Executes a handler on each item in the list." & RETURN after msg
  put "map( handler{, object} )                        -- Executes a handler on each item in a list, and constructs a new list of items corresponding to the results of the handler on each item in the original list." & RETURN after msg
  put "sortOn( intColumnIndex{, symbolOrder} )         -- Sorts the list on given "&quote&"column"&quote&"." & RETURN after msg
  put "concat()                                        -- Concatenates the elements specified in the parameters with the elements in a list and creates a new list." & RETURN after msg
  put "reverse()                                       -- Reverses the list in-place." & RETURN after msg
  put "join( separator )                               -- Returns a string, constructed by items in the list, with the separator inserted between them." & RETURN after msg
  put "toString()                                      -- Returns a string that represents the elements in the specified list, separated by commas." & RETURN after msg
  put "lastIndexOf( searchElement, startIndex )        -- Searches for an item in a list, working backward from the last item, and returns the index position of the matching item." & RETURN after msg
  put "typeOf()                                        -- Returns the name of the script as a symbol." & RETURN after msg
  put "is()" after msg
  return msg
end interface

-------------------------------------------------
-- PRIVATE METHODS
-------------------------------------------------
on ___________________________PRIVATE_METHODS
end
on __sort_on_internal_ASC( me, c )
  t = list()
  t[ c ] = 0
  ancestor.add( t )
  cnt = count( ancestor )
  repeat with i = cnt down to 0
    flipped = FALSE
    j = 0
    repeat while j < i
      j = j + 1
      if ( j + 1 < cnt ) then
        aInt = float( ancestor[ j ][ c ] )
        bInt = float ( ancestor[ j + 1 ][ c ] )
        if ( aInt > bInt ) then
          t = ancestor[ j ]
          ancestor[ j ] = ancestor[ j + 1 ]
          ancestor[ j + 1 ] = t
          flipped = TRUE
        end if
      end if
    end repeat
  end repeat
  ancestor.deleteAt( cnt )
  return TRUE
end __sort_on_internal_ASC

on __sort_on_internal_DESC( me, c )
  t = list()
  t[ c ] = 0
  ancestor.add( t )
  cnt = count( ancestor )
  repeat with i = cnt down to 0
    flipped = FALSE
    j = 0
    repeat while j < i
      j = j + 1
      if ( j + 1 < cnt ) then
        aInt = float( ancestor[ j ][ c ] )
        bInt = float ( ancestor[ j + 1 ][ c ] )
        if ( aInt < bInt ) then
          t = ancestor[ j ]
          ancestor[ j ] = ancestor[ j + 1 ]
          ancestor[ j + 1 ] = t
          flipped = TRUE
        end if
      end if
    end repeat
  end repeat
  ancestor.deleteAt( cnt )
  return TRUE
end __sort_on_internal_DESC

on ___________________________END_XLIST
end

EXAMPLES (try this in message window) :

myList = script( "xList" ).new( 1, 2, 3 )
myList.reverse()
put myList.toString()    -- "3,2,1"
put myList[1]            -- 3
put myList[10]           -- <Void>
myList.add( 4, 5, 6 )
put myList.toString()    -- "3,2,1,4,5,6"
myList.sort()
put myList.toString()    -- "1,2,3,4,5,6"

An example of filter() method:

myList = script( "xList" ).new( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 )
put myList.filter( #getEven ).toString() -- "2,4,6,8,10"

-- A handler, defined in a movie script:
on getEven( aelement )
  return( aelement mod 2 = 0 )
end getEven
1 Star2 Stars3 Stars4 Stars5 Stars (16 votes, average: 4.63 out of 5)
Loading ... Loading ...
154 views

No Comments

Leave a Reply

Your email is never shared.