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. |
sort( {symbolOrder} ) | – | Sorts the list in ascending or descending order.( #ASC / #DESC ) |
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. |
[code lang=”lingo” gutter=”true” toolbar=”true” collapse=”false”]
— "Xlist" parent script
— Author: Vladin M. Mitov
— May, 2011
— Last Update – February, 2012
— https://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, s, 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 sort( me, order )
if( voidP( order ) or [#ASC, #DESC].getPos( order ) = 0 ) then order = #ASC
case( order ) of
#ASC :
callAncestor( #sort, me )
#DESC:
callAncestor( #sort, me )
me.reverse()
end case
end sort
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 ""e&"Index out of range""e&" exception." & RETURN after msg
put "deleteAt()* — Prevents ""e&"Index out of range""e&" 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 "sort( {symbolOrder} ) — Sorts the list ascending or descending ( #ASC / #DESC )" & RETURN after msg
put "sortOn( intColumnIndex{, symbolOrder} ) — Sorts the list on given ""e&"column""e&"( #ASC or #DESC )." & 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
[/code]
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
Added sort() method.
sort( {order} )
order – #Symbol; #ASC or #DESC