The LIST function creates a new list. A list is a compound data type that contains elements of different data types, including any mixture of scalars, arrays, structures, pointers, object references, and other lists or hashes.

Lists have the following properties:

  • Elements in a list are ordered, and are indexed in one dimension.
  • Lists can change their size, growing and shrinking as elements are added or deleted.
  • Individual list elements can change their value and data type without a performance penalty.
  • List is implemented using a C++ std::list of values.

Difference between Arrays and Lists

  • IDL arrays can only contain elements of the same data type. The elements are stored in a contiguous block of memory. Adding or removing elements is always an expensive operation because the new memory must be allocated and all elements of the existing array must be copied. Indexing individual elements within an array is always fast, because simple math can be used to determine the memory locations.
  • IDL lists can contain elements of any data type. The elements are stored in an std::list<IDL_VPTR>. Adding or removing elements from the beginning or end of the list is fast, because the list contains a special pointer to the head and tail. Adding or removing elements from the middle of the list will be slower because the linked list must be traversed. However, even in this case, it may still be faster than using an array because no memory needs to be copied. Indexing into the middle of a list will be slower than an array.

Methods and Additional Information

  • List::Add: Add a new item to the list.
  • List::Count: Return the number of items in the list.
  • List::Filter: Pass the items through a filter function.
  • List::IsEmpty: Test whether the list is empty.
  • List::Map: Pass the items through a user-defined function.
  • List::Move: Move items in the list.
  • List::NestedMap: Pass the items through a user-defined function using a nested loop.
  • List::Reduce: Pass each item through a function, accumulating the result.
  • List::Remove: Remove an item from the list.
  • List::Reverse: Reverse all elements in the list.
  • List::Sort: Sort the list.
  • List::Swap: Switch the positions of two items in the list.
  • List::ToArray: Convert the list to an IDL array.
  • List::Where: Find where items are equal to a certain value.
  • Concatenating Lists
  • Comparing Lists

    • EQ Operator
    • NE Operator
  • List Access

    • Retrieve a Single Element
    • Insert a Single Element
    • Change the Value of a Single Element
    • Create a Sub-List
    • Insert Multiple Elements
    • Change the Value of Multiple Elements
    • Copy a List
    • Iterate Through a List
    • Access and Change Array Elements within a List
  • Information about Lists

    • Logical Truth
    • Logical Negation
    • N_ELEMENTS
    • ISA
    • TYPENAME
    • HELP
    • PRINT
    • Implied Print

The LIST function and class was ported from PRO code to C/C++ code in 8.8.1. You can run the SAVEFILE_CLEANUP procedure to inspect an older save file and remove any routines that might cause problems in IDL 8.8.1 and newer. See SAVEFILE_CLEANUP for more information.

Syntax


Result = LIST( [Value1, Value2, ... Valuen] [, /EXTRACT] [, LENGTH=value] [, /NO_COPY])

Return Value


Returns a reference to a newly-created list.

Arguments


Valuen

Each Value argument can be a variable or expression of any IDL data type including !NULL. If no Value argument is supplied, a reference to an empty list is returned.

Keywords


EXTRACT

Normally, if a Value argument refers to an array or a list, that array or list is inserted into the new list as a single element. If the EXTRACT keyword is specified, any Value argument that contains an array or a list will be disassembled, and each element of the array or list will be added to the new list as a separate element. The EXTRACT keyword has no effect if none of the Value arguments are arrays or lists.

LENGTH

Set this keyword to an integer value to create a list with the specified number of elements. If LENGTH is greater than the number of Value arguments, the Value arguments supplied are cyclically repeated to fill out the list. If no Value arguments are supplied, all list elements will contain the value !NULL.

NO_COPY

If the NO_COPY keyword is set, the value data is taken away from the Value variable and attached directly to the list variable. The default behavior is to make a copy of the input values.

Examples


Create a list containing seven scalar values:

list=LIST('one', 2.0, 3, 4l, PTR_NEW(5), {n:6}, COMPLEX(7,0))

Create a list containing two arrays:

array1 = [2,3,4,5]
array2 = [2.0,3.0,4.0,5.0]
list1 = LIST(array1, array2)
PRINT, N_ELEMENTS(list1)

IDL Prints:

2

Create a list containing all of the elements of an array:

array1 = [2,3,4,5]
list2 = LIST(array1, /EXTRACT)
PRINT, N_ELEMENTS(list2)

IDL Prints:

4

List::Add


The List::Add procedure method adds elements to an existing list. In its simplest form, List::Add places a single value on the end of the specified list. The optional Index argument allows you to insert an element at a specific list index. When used in conjunction with the List::Remove method, List::Add makes it easy to implement a stack or queue using a LIST variable.

Syntax


list.Add,Value [, Index] [, /EXTRACT] [, /NO_COPY]

Arguments


Value

A variable or expression of any IDL data type including !NULL.

Index

The zero-based index at which to insert the Value argument. The element that previously occupied the position specified by Index, and all elements that follow it, will have their index values incremented. If theEXTRACT keyword is set and Value is and array or list, then all the new elements will be inserted starting at this position. If Index is negative, it will count from the end forwards to define the position of the new element(s). If Index is not specified, the Value argument is added to the end of the list.

Keywords


EXTRACT

Normally, if the Value argument refers to an array or a list, that array or list is inserted into the list as a single element. If the EXTRACT keyword is specified, and the Value argument contains an array or a list , it will be disassembled, and each element of the array or list will be added to the list as a separate element. The EXTRACT keyword has no effect if the Value argument is neither an array nor a list.

NO_COPY

If the NO_COPY keyword is set, the value data is taken away from the Value variable and attached directly to the list variable. The default behavior is to make a copy of the input values.

Examples


list = LIST(1, 2, 3)
list.Add, 4
PRINT, list

IDL Prints:

1   2   3   4
 
list.Add, 100, 0
PRINT, list

IDL Prints:

100   1   2   3   4
 
list.Add, [2.1, 2.2, 2.3], 3, /EXTRACT
PRINT, list

IDL Prints:

100   1   2   2.1   2.2   2.3   3   4

List::Count


The List::Count function method returns the number of elements in the list. Optionally, the List::Count method can return the number of matches to a given value.

Syntax


Result = list.Count( [Value] )

Return Value


By default, returns an integer containing the number of elements in the list. If Value is supplied, returns an integer giving the number of occurrences of Value within the list.

Note: See the List::Where method for the rules that are used for comparing values.

Arguments


Value

A value to search for within the list.

Keywords


None

List::Filter


The List::Filter method passes each list value through a Boolean filter function or Lambda function and returns a List containing only values that pass the test.

Examples


Create a new file called myfilterfunction.pro that keeps only prime numbers:

function myfilterfunction, value
  return, value le 3 || MIN(value mod [2:FIX(SQRT(value))])
end

Use your function to return only the prime numbers in an array:

var = LIST([2:50], /EXTRACT)
newvar = var.Filter('myfilterfunction')
PRINT, newvar.ToArray()

IDL prints:

2  3  5  7 11 13 17 19 23 29 31 37 41 43 47

Now use a Lambda function to avoid creating a separate routine:

var = LIST([2:50], /EXTRACT)
newvar = var.Filter(Lambda(n:n le 3 || MIN(n mod [2:FIX(SQRT(n))])))

Tip: The COMPILE_CODE procedure can be used to generate functions on the fly.

Syntax


Result = list.Filter( Function, Args )

Return Value


The result is a list containing only the values where the filter function returned a non-zero number for that input value. If none of the values are good then the method returns an empty list.

Arguments


Function

A string or Lambda expression giving the name of the user-defined function to call for each value. For user-defined functions, your function should have the form:

function myfunction, value
  result = ...
  return, result
end

The result should be a scalar value containing a non-zero value if the input value "passes" your filter test, and a zero value if the input value "fails" your filter test.

Args

You can specify any number of additional arguments to be passed on to your filter or Lambda function. Each argument must be either a scalar, an array of the same length as your input, or a list of the same length as your input. For scalar arguments, ::Filter will pass in that same scalar value to each call of the filter function. For array or list arguments, ::Filter will pull out the value corresponding to the current input value and pass that into your filter function as a scalar.

Keywords


None.

List::IsEmpty


The List::IsEmpty function method tests whether the list is empty or not.

Syntax


Result = list.IsEmpty( )

Return Value


Returns 1 if the list contains zero elements, and 0 otherwise.

Arguments


None.

Keywords


None.

List::Map


The List::Map method passes each list value through a user-defined function or Lambda function and returns a List containing the mapped values.

Examples


Create a new file called mymapfunction.pro that returns a cubic polynomial:

function mymapfunction, x, a, b, c
  return, (x - a)^3.0 + (x - b)^2 + (x - c)
end

Use your function to map a list to the new values:

var = LIST([-2: 2: 0.01], /EXTRACT)
; Each var value is passed in separately
newvar = var.Map('mymapfunction', 1, 2, 0)
print, var.ToArray(), newvar.ToArray()

IDL prints:

-2.00000     -1.99000     -1.98000     -1.97000     -1.96000 ...
-13.0000     -12.8008     -12.6032     -12.4072     -12.2127 ...

Now use a Lambda function to avoid creating a separate routine:

var = LIST([-2: 2: 0.01], /EXTRACT)
; Each var value is passed in separately
newvar = var.Map(Lambda(x,a,b,c:(x-a)^3.0+(x-b)^2+(x-c)), 1, 2, 0)

Tip: The COMPILE_CODE procedure can be used to generate functions on the fly.

Syntax


Result = list.Map( Function, Args )

Return Value


The result is a list containing the new values.

Arguments


Function

A string or Lambda expression giving the name of the user-defined function to call for each value. For user-defined functions, your function should have the form:

function myfunction, value
  result = ...
  return, result
end

The result can be a value of any type. This result will be inserted into the returned list.

Args

You can specify any number of additional arguments to be passed on to your user-defined function or Lambda function. Each argument must be either a scalar or an array or list of the same length as your input. For scalar arguments, ::Map will pass in that same scalar value to each call of the function. For vector arguments, ::Map will pull out the value corresponding to the current input value and pass that into your function as a scalar.

Keywords


None.

List::Move


The List::Move method moves an element from one index in the list to a new index. The order of the other elements in the list remains unchanged, although their indices may be shifted, based on the location of the moved element.

Syntax


list.Move, Source, Destination

Arguments


Source

The zero-based index of the current location of the element that will move. A negative value will count from the end forwards.

Destination

The zero-based index of the new location where the element will move. A negative value will count from the end forwards.

Keywords


None

Example


list = LIST(0, 1, 2, 3, 4)
list.Move, 1,4
PRINT, list

IDL prints:

0, 2, 3, 4, 1

List::NestedMap


The List::NestedMap method passes each list value along with other arguments through a user-defined function or Lambda function. Each list value is combined with every element from the other arguments using a nested loop. This operation also goes by the name "list comprehension" or "Cartesian product". You can also supply an optional filter function to remove unwanted results.

Difference between Map and NestedMap

Assume we have two lists, a and b, with three elements each. For a given map function F(a,b):

a.Map(F, b) returns a list containing:

[F(a[0], b[0]), F(a[1], b[1]), F(a[2], b[2])]

a.NestedMap(F, b) returns a list containing:

[ F(a[0], b[0]), F(a[1], b[0]), F(a[2], b[0]),
  F(a[0], b[1]), F(a[1], b[1]), F(a[2], b[1]),
  F(a[0], b[2]), F(a[1], b[2]), F(a[2], b[2]) ]

Example


Return a new list containing every combination of items from two lists:

l1 = LIST('a', 'b', 'c')
l2 = LIST('d', 'e', 'f')
l3 = l1.NestedMap(Lambda(x,y:x+y), l2)
help, l3
print, l3.ToArray()

IDL prints:

L3              LIST  <ID=15  NELEMENTS=9>
ad bd cd ae be ce af bf cf

Syntax


Result = list.NestedMap( Function, Args , FILTER=string)

Return Value


The result is a list containing the new values.

Arguments


Function

A string or Lambda expression giving the name of the user-defined function to call for each value. For user-defined functions, your function should have the form:

function myfunction, value, arg1, arg2, ...
  result = ...
  return, result
end

The result can be a value of any type. This result will be inserted into the returned list.

Args

You can specify additional arguments. Each argument must be either a scalar, array, or list of any length. For scalar arguments, ::NestedMap will pass in that same scalar value to each call of the function. For vector arguments, ::NestedMap will perform a nested loop over all elements of that argument plus all other arguments. The nested loop is performed from left to right across the arguments, starting with the original list variable.

Keywords


FILTER

Set this keyword to a string or Lambda expression giving the name of a user-defined filter function. The function should have the form:

function myfilter, result
  good = some function of result...
  return, good ? 1 : 0
end

This function will be called for each result value. The function should return 1 (true) if the result should be added to the Result list, 0 (false) if the result should be discarded, or –1 if the NestedMap should stop early and return just the results up to (but not including) that result.

More Examples


Use a Lambda function to return triangles that satisfy the Pythagorean theorem. First construct a new list containing triplets of all combinations of numbers between 1 and 20:

x = LIST([1:20], /EXTRACT)
p = x.NestedMap(Lambda(x,y,z:[x,y,z]), x, x)
help, p

IDL prints:

P               LIST  <ID=75  NELEMENTS=8000>

This is not what we want. We need to keep only triplets that satisfy x^2 + y^2 = z^2. Use the FILTER keyword to keep only these values:

p = x.NestedMap(Lambda(x,y,z:[x,y,z]), x, x, FILTER=Lambda(r:r[2]^2 eq r[0]^2+r[1]^2))
help, p
print, p[0:1] ; print the first two triplets

IDL prints:

P               LIST  <ID=29847  NELEMENTS=12>
4   3   5
3   4   5

This still isn't what we want because it has duplicate triplets. Change the filter function to exclude duplicates:

p = x.NestedMap(Lambda(x,y,z:[x,y,z]), x, x, $
  FILTER=Lambda(r:(r[0] le r[1]) && (r[2]^2 eq r[0]^2+r[1]^2)))
help, p
print, p

IDL prints:

P               LIST  <ID=29877  NELEMENTS=6>
3    4    5
6    8   10
5   12   13
9   12   15
8   15   17
12  16   20

Tip: The COMPILE_CODE procedure can be used to generate functions on the fly.

List::Reduce


The List::Reduce method passes each data value cumulatively from left to right through a user-defined function or Lambda function and returns a scalar result.

Examples


Create a new file called myreducefunction.pro that adds up arrays (or concatenates strings):

function myreducefunction, accumvalue, value
  return, accumvalue + value
end

Use your function on a string array:

var = LIST('IDL', ' ', 'is', ' ', 'fun', '!')
newvar = var.Reduce('myreducefunction')
PRINT, newvar

IDL prints:

IDL is fun!

Now use a Lambda function to avoid creating a separate routine:

var = LIST('IDL', ' ', 'is', ' ', 'fun', '!')
newvar = var.Reduce(Lambda(x,y:x+y))

Finally, use the /CUMULATIVE to return all of the intermediate results:

newvar = var.Reduce(Lambda(x,y:x+y), /CUMULATIVE)
PRINT, newvar, /IMPLIED

IDL prints:

[
  "IDL",
  "IDL ",
  "IDL is",
  "IDL is ",
  "IDL is fun",
  "IDL is fun!"
]

Tip: The COMPILE_CODE procedure can be used to generate functions on the fly.

Syntax


Result = list.Reduce( Function, Args, /CUMULATIVE, VALUE=value)

Return Value


The result is a scalar value containing the cumulative result. The data type of the result will depend upon your calling function's result type.

If your input contains a single element then this value will be returned as the result without calling the function, unless the VALUE keyword is set, in which case the function will be called once.

Tip: You can use the /CUMULATIVE keyword to return all of the intermediate results instead of just the final result.

Arguments


Function

A string or Lambda expression giving the name of the user-defined function to call for each value. For user-defined functions, your function should have the form:

function myfunction, accumvalue, value
  result = ...
  return, result
end

The result should be a scalar value that combines the current accumulated value (the first argument) and the current input value (the second argument).

Args

You can specify any number of additional arguments to be passed on to your user-define function or Lambda function. Each argument must be either a scalar or an array or list of the same length as your input. For scalar arguments, ::Reduce will pass in that same scalar value to each call of the filter function. For vector arguments, ::Reduce will pull out the value corresponding to the current input value and pass that into your function as a scalar.

Keywords


CUMULATIVE

If this keyword is set, then the Result will be a list containing all of the intermediate cumulative results instead of just the final result.

VALUE

Set this keyword to the starting value. If this keyword is set then this value will be passed into your function along with the first element of your input. If this keyword is not set then the first two elements will be passed into your function.

List::Remove


The List::Remove method removes elements from a list and optionally returns the removed value(s).

Syntax


list.Remove [, /ALL]

or

list.Remove, Indices

or

Value = list.Remove( [, /ALL] )

or

Value = list.Remove( Indices )

Return Value


If List::Remove( ) is called with no arguments then the last element is removed and returned.

If List::Remove( ) is called with a single Index, it returns the value of the specified element.

If List::Remove( ) is called with multiple Indices (or the ALL keyword), it returns a new list containing the specified elements.

Note: If the list is empty, calling the List::Remove() function method will throw an error (unless Indices is equal to !NULL). The List::Remove procedure method will quietly return.

Arguments


Indices

A scalar index or array of indices of list elements to be removed. If no Indices are supplied, the last element is removed. If Indices is equal to !NULL then nothing is removed and !NULL is returned from the function call.

Keywords


ALL

Set this keyword to remove all entries in List, leaving the list empty, but still in existence.

Examples


Create a list and print its contents:

list = LIST(98.6, 'narwhal', [2, 4, 6, 8], COMPLEX(3,3))
PRINT, list

IDL Prints:

    98.6
narwhal
    2 4 6 8
( 3.00000, 3.00000)

Now delete some list elements and print the contents again:

list.Remove, [1, 3]
PRINT, list

IDL Prints:

    98.6
    2 4 6 8

Show the number of elements in the list:

PRINT, N_ELEMENTS(list)

IDL Prints:

    2

Now remove the last element off the list, printing the removed value:

PRINT, list.Remove()

IDL Prints:

    2 4 6 8

List::Reverse


The List::Reverse procedure method modifies the list to reverse the order of it elements.

Syntax


list.Reverse

Arguments


None.

Keywords


None.

Examples


Create a list, then reverse it and print its contents:

list = LIST(98.6, 'narwhal', [2, 4, 6, 8], COMPLEX(3,3))
list.Reverse
PRINT, list

IDL Prints:

( 3.00000, 3.00000)
    2 4 6 8
narwhal
    98.6

List::Sort


The List::Sort method sorts all of the list elements and returns a new list.

The list elements should all have the same dimensions and compatible data types, unless you use your own compare function (see the COMPARE_FUNCTION keyword).

Syntax


result = list.Sort( COMPARE_FUNCTION=string, COUNT=integer, INDICES=variable, /OVERWRITE, /REVERSE )

Arguments


None

Keywords


COMPARE_FUNCTION

A string or Lambda function giving the name of a user-defined "compare" function. The function should have the form:

function myfunc, value1, value2

The function should return –1 if value1 should be considered "less than" value2, +1 if value1 is "greater than" value2, or 0 if the two list elements are "equal". By default, the ::Sort method uses IDL's standard rules for comparing values.

Tip: The IDL_Variable::Compare method may be helpful when constructing compare functions. See the examples below.

COUNT

Set this keyword to an integer giving the number of elements to sort. You can use this keyword to sort just the first part of the list.

INDICES

Set this keyword to a named variable. On return this variable will contain a one-dimensional integer array of subscripts that were used to sort the original values.

OVERWRITE

Set this keyword to replace the contents of the list with the sorted result. This avoids creating a new list and can save a significant amount of memory.

Note: The result will be a reference to the original list. If you assign this result to a new variable then both the new variable and the original variable will point to the same list.

REVERSE

Set this keyword to sort the list in reverse order.

Example


Simple sort

Do a simple sort of an integer list:

list = LIST(0, 4, 2, 1, 5)
result = list.Sort( )
PRINT, result

IDL prints:

0 1 2 4 5
Sort with a compare function

Now define a list of structures, and use a compare function to sort on one of the structure keys. Here we will use the IDL_Variable::Compare method to perform the comparison. First create a named structure and construct a list of these structures:

void = {Planet, NAME: "", MASS: 0.0}
p = LIST({Planet, "Earth", 1}, {Planet, "Mercury", 0.055}, $
  {Planet, "Venus", 0.815}, {Planet, "Mars", 0.107})

Now create the compare function:

function struct_compare, v1, v2
  ; Return -1, 0, or 1 depending upon the name field
  return, (v1.NAME).Compare(v2.NAME)
end

Now do the sort:

result = p.Sort(COMPARE_FUNCTION='struct_compare')
PRINT, result

IDL prints:

{ Earth      1.00000}
{ Mars     0.107000}
{ Mercury    0.0550000}
{ Venus     0.815000}
Sort using a Lambda function

Now sort on the planet mass, but use a Lambda function:

result = p.Sort(COMPARE_FUNCTION=Lambda(a,b:(a.MASS).Compare(b.MASS)))
PRINT, result

IDL prints:

 { Mercury    0.0550000}
{ Mars     0.107000}
{ Venus     0.815000}
{ Earth      1.00000}

List::Swap


The List::Swap method swaps two elements in the list. The order and indices of all other elements in the list remain unchanged.

Syntax


list.Swap, Index1, Index2

Arguments


Index1

The zero-based index of the first element to swap. A negative value will count from the end forwards.

Index2

The zero-based index of the second element to swap. A negative value will count from the end forwards.

Keywords


None

Example


list = LIST(0, 1, 2, 3, 4)
list.Swap, 1, 4
PRINT, list

IDL prints:

0, 4, 2, 3, 1

List::ToArray


The List::ToArray function method returns an array containing all of the list values, converted to a single data type. The TYPE keyword may be used to control the result type, while the MISSING keyword may be used to control the behavior for missing or incompatible values.

If the list contains all scalar values then the result will be a vector with the same number of elements as the list. If the list contains arrays of the same size then the result will be an array of one higher dimension, where the first dimension will contains the same number of elements as the list, and the higher dimensions will match the array dimensions. For example, if the list contains 5 elements, each of which is a [10, 20] array, then the List::ToArray method will return a [5, 10, 20] array. Array elements of different shapes can be handled, if they have the same number of elements.

Tip: The DIMENSION keyword may be used to concatenate list elements instead of creating an array of a higher dimension.

Note: If the list contains only one element, and it is a scalar, then the result will be a 1-element array.

Note: If the list contains only one element, and it is an array, then the result will be an array where the first dimension is 1. For example, if the list contains a single vector of length 100, then the result will be an array of dimensions [1, 100]. If you also use the /TRANSPOSE keyword then the trailing dimension of 1 will be dropped, and the result will be an array of the same dimensions as the list element.

Note: If the list contains arrays of different dimensions, IDL will throw an error unless the MISSING keyword is also specified.

Syntax


Result = list.ToArray( DIMENSION=value, MISSING=value, /NO_COPY, /PROMOTE_TYPE, /TRANSPOSE, TYPE=value )

Return Value


The result is an array containing all of the list values, converted to the same IDL data type. If the list is empty then !NULL is returned.

Arguments


None.

Keywords


DIMENSION

Set this keyword to the 1-based dimension over which to concatenate the arrays contained within the list. For this keyword to work correctly, each element of the list must have the same number of elements in each dimension except for the dimension given by DIMENSION. For example, assume your list contains three arrays and you wish to concatenate over the second dimension:

l = LIST(FLTARR(3,10,5), FLTARR(3,12,5), FLTARR(3,7,5))
result = l.ToArray(DIMENSION=2)
help, result

IDL prints:

RESULT          FLOAT     = Array[3, 29, 5]

Note: If the DIMENSION keyword is specified, the MISSING and TRANSPOSE keywords are ignored.

Tip: If your list has a mixture of scalars and 1-D arrays (vectors) you can set DIMENSION=1 to concatenate all of the elements into a single 1D array.

MISSING

Set this keyword to a value of the same type as the returned result, or can be typecast to that type. The default behavior of the List::ToArray method is to throw an error if a list element cannot be converted to the desired data type or dimensions. If MISSING is set, and a list element cannot be converted, then the MISSING value is returned for that element. If the list contains arrays instead of scalars then MISSING may either be a scalar (in which case every element of a missing sub-array is set to that value) or MISSING must be an array with the same number of elements as the arrays within the list.

NO_COPY

Set this keyword to move each element from the list to the output array. When finished, the list will be empty.

PROMOTE_TYPE

By default, the data type of the result is just the type of the first element in the list (unless TYPE is set). Set the PROMOTE_TYPE keyword to true (1) to examine every element in the list to find the "highest" type. The ::ToArray method will set the result to this data type and will convert all of the result values to this type. When determining which of two data types is "higher", List::ToArray uses the following rules from top-to-bottom (stopping when a rule is matched):

  • STRING + any lower type = STRING
  • DCOMPLEX + any lower type = DCOMPLEX
  • DOUBLE + COMPLEX = DCOMPLEX
  • DOUBLE + any lower type = DOUBLE
  • COMPLEX + any lower type = COMPLEX
  • FLOAT + any lower type = FLOAT
  • LONG64 + any lower type = LONG64
  • ULONG64 + any lower type = ULONG64
  • LONG + any lower type = LONG
  • ULONG + any lower type = ULONG
  • INT + any lower type = INT
  • UINT + any lower type = UINT
  • BYTE + any lower type = BYTE

Note: If the List contains any Pointer, ObjRef, or Struct elements, then all elements must be of that same type to succeed.

TRANSPOSE

If the list contains arrays instead of scalars, then the default behavior is to have the first dimension contain the number of list elements. Set this keyword to transpose the resulting array so that the last dimension contains the list elements. For example, if the list contains 5 elements, each of which is a [10, 20] array, then by default the List::ToArray method will return a [5, 10, 20] array. If TRANSPOSE is set then the result will be a [10, 20, 5] array.

TYPE

Set this keyword to an integer or a string giving the IDL type code of the result array. All values within the list will then be converted to this type. The default behavior is to use the type of the first element in the list.

Note: You can set TYPE='Boolean' to return a Boolean array, with standard Boolean typecasting of string and numeric elements. Pointer, ObjRef, and Struct elements in the List will throw an error.

Examples


Mixed Data Types

Create a list of mixed types, then return an array of a single type:

list = LIST(1, 2uL, 3.14, COMPLEX(4))
 
; Default behavior is to return the same type as the first element
arr = list.ToArray()
 
HELP, arr
PRINT, arr

IDL prints:

ARR              INT       = Array[4]
1      2       3       4

Now force the data type:

list = LIST(1, 2uL, 3.14, COMPLEX(4))
arr = list.ToArray(TYPE='FLOAT')
HELP, arr
PRINT, arr

IDL prints:

ARR     FLOAT     = Array[4]
1.00000      2.0000      3.14000      4.00000

Now use PROMOTE_TYPE to pick the "highest" type:

list = LIST(1, 2uL, 3.14, COMPLEX(4))
arr = list.ToArray(/PROMOTE_TYPE)
HELP, arr
PRINT, arr

IDL prints:

ARR             COMPLEX   = Array[4]
(      1.00000,     0.000000)(      2.00000,     0.000000)(      3.14000,     0.000000)(      4.00000,     0.000000)

Missing Values

Now add some non-numeric values, and use the MISSING keyword:

list = LIST(1, 'oops', 3.14, !NULL)
 
arr = list.ToArray(TYPE='INT', MISSING=-99)
 
HELP, arr
PRINT, arr

IDL prints:

ARR             INT       = Array[4]
1     -99       3     -99
 

Create a list of arrays, then return an array of higher dimension:

list = LIST(FINDGEN(10), INDGEN(10), BYTARR(10))
 
; Default behavior is to return the same type as the first element
HELP, list.ToArray()
 
; Now use the TRANSPOSE keyword to flip the dimensions
HELP, list.ToArray(/TRANSPOSE)

IDL prints:

ARR              FLOAT      = Array[3, 10]
ARR              FLOAT      = Array[10, 3]

Array Concatenation

Use the DIMENSION keyword to speed up array concatenation:

; First use standard array concatenation,
; building up a new array one chunk at a time.
tic
vertices = [ ]
for i=0,9999 do begin & $
  n = 10 + FIX(10*RANDOMU(seed)) & $
  vert1 = RANDOMU(seed, 3, n) & $
  vertices = [[vertices], [vert1]] & $
endfor
HELP, vertices
toc
 
; Now use ::ToArray to do the concatenation.
tic
vertexList = LIST()
for i=0,9999 do begin & $
  n = 10 + FIX(10*RANDOMU(seed)) & $
  vert1 = RANDOMU(seed, 3, n) & $
  vertexList.Add, vert1 & $
endfor
vertices = vertexList.ToArray(DIMENSION=2)
HELP, vertices
toc

IDL prints:

VERTICES        FLOAT     = Array[3, 144747]
% Time elapsed: 1.8260000 seconds.
 
VERTICES        FLOAT     = Array[3, 145240]
% Time elapsed: 0.20199990 seconds.

Notice that using LIST concatenation is significantly faster than reallocating and copying the array each time through the loop.

List::Where


The List::Where function method returns an array of indices for those list elements that are equal to a certain value.

Note: The method call list.Where(Value) is equivalent to calling WHERE(list EQ Value), and is provided as a programming convenience.

Syntax


Result = list.Where( Value [, COMPLEMENT=variable] [, COUNT=variable] [, NCOMPLEMENT=variable] )

Return Value


Returns an array of integers containing the list subscripts. If there are no matches, !NULL is returned. The following rules are used when comparing values:

  • If Value is a scalar number, string or !NULL, the corresponding list element must be equal to the same value (although the types may differ).
  • If Value is an array, the corresponding list element must be an array of the same length, with identical values (although the types may differ).
  • If Value is a pointer or object, the corresponding list element must be the same pointer or object reference.
  • If Value is a structure, it is compared to the corresponding list element on a tag-by-tag basis (including nested structures) using the same rules as above.
  • If Value is another list, the two lists are compared on an element-by-element basis (using the above rules), and the result is an array of integers containing the list subscripts where the values are equal. If the lists are not the same length then the shortest length is used.

Arguments


Value

A variable or expression of any IDL data type, including !NULL.

Keywords


COMPLEMENT

Set this keyword to a named variable that will return an array of integers containing the list subscripts that do not contain the value.

COUNT

Set this keyword to a named variable that will return the number of matches.

NCOMPLEMENT

Set this keyword to a named variable that will return the number of indices within the COMPLEMENT array.

Examples


The following example generates a random integer and an array of ten random integers (both between 0 and 9). The sample uses Where to determine if there are any matches of the value in the list.

rndmVal = FIX(10 * RANDOMU(seed, 1))
rndmArr = FIX(10 * RANDOMU(seed, 10))
l = LIST(rndmArr, /EXTRACT)
matches = l.Where(rndmVal)
PRINT, 'Random value = ', rndmVal
PRINT, 'Random array = ', rndmArr
PRINT, 'Matching indices = ', matches

Sample output:

Random value =        7
Random array =        6       9       4       7       2       5       9       5       7       8
Matching indices =            3           8

Additional Information on Lists


Concatenating Lists


To combine two lists to make a new list, use the + operator:

list1 = LIST('zero', 1, 2.0)
list2 = LIST(!PI, COMPLEX(4,4), [5,5,5,5,5])
list3 = list1 + list2
PRINT, list3

IDL prints:

zero
     1
     2.00000
     3.14159
(    4.00000,  4.00000)
     5     5     5     5     5

Note that

list3 = list1 + list2

is exactly equivalent to:

list3 = LIST()
list3.Add, list1, /EXTRACT
list3.Add, list2, /EXTRACT

In-place concatenation can also be performed, using the += operator:

list1 = LIST('zero', 1, 2.0)
list2 = LIST(!PI, COMPLEX(4,4), [5,5,5,5,5])
list1 += list2

Here list1 is now the same as list3 above.

Comparing Lists


EQ

The EQ operator does an element-by-element comparison. The operator syntax is list1 EQ list2, and EQ returns a byte array of 1s (the elements are equal) or 0s (the elements are not equal). The length of the result is the length of the shortest list. If both lists are empty lists, the scalar value 1 is returned.

Note: See the List::Where method for the rules that are used for comparing values.

To compare two lists:

list1 = LIST('alpha', 5, 19.9)
list2 = LIST('alpha', 'abc', 19.9)
PRINT, list1 EQ list2

IDL Prints:

1 0 1

When comparing each element of a list with a value (a scalar or array of any type) of the form list EQ value, the EQ operator returns a byte array of 1s or 0s. The length of the result is the length of the list. If the list is an empty list, the scalar value 0 is returned.

To compare a list with a scalar value:

list3 = LIST('beta', 99, 300.73)
value = 99
PRINT, list3 EQ value

IDL Prints:

0 1 0

To compare a list with an array:

list4 = LIST(3, 7, 9, 12, [4, 33, 9, 64, 43], 'alpha')
array = [4, 33, 9, 64, 43]
PRINT, list4 EQ array

IDL Prints:

0 0 0 0 1 0

Note: IDL treats the array as a single item for the comparison.

NE

The NE operator behaves in the opposite manner of EQ. Instead of returning the byte value 1 for a match, NE returns the byte value 1 if two list elements are not a match.

List Access


In many cases, you can access elements of a list variable using standard IDL array syntax, as if the list were a one-dimensional array.

Retrieve a Single Element

To copy the value of a single list element into a new variable, leaving the list unchanged, use array syntax:

value = list[Index]

where Index is the zero-based index of the desired element within the list. Negative indices may be used to index from the end. For example, list[-1] would retrieve the last element.

To retrieve the last element in a list and remove it, use the list.Remove function method:

value = list.Remove()

To retrieve a specific element in a list and remove it:

value = list.Remove(Index)

where Index is the zero-based index of the desired element within the list.

Insert a Single Element

To insert a single value at the end of a list, creating a new list element, use the list.Add method:

list.Add, Value

where Value is the value to be stored in the new list element.

To insert a single value at a specified position within a list:

list.Add, Value, Index

where Value is the value to be stored in the new list element, and Index is the zero-based index of the position at which the element should be inserted.

Change the Value of a Single Element

To change the value of a single list element, use array syntax:

list[Index] = Value

where Index is the zero-based index of the desired element within the list and Value is the new value.

Create a Sub-list

To create a new list that is a subset of an existing list, use array syntax:

newList = origList[ [Index0, Index1, ..., Indexn-1] ]

Here newList is a new list variable that contains copies of the elements from origList specified by the indices Index0, Index1, ..., Indexn-1.

You can also create a sub-list using the array minimum and maximum index syntax:

newList = origList[minIndex:maxIndex]

For example:

newList = origList[4:8]

would create a new list variable consisting of the fifth through ninth elements of origList.

Similarly, you can use the minimum, maximum, and stride syntax:

newList = origList[minIndex:maxIndex:stride]

For example:

newList = origList[3:15:3]

would create a new list variable consisting of elements 3, 6, 9, 12, and 15 of origList.

Insert Multiple Elements

To insert multiple elements into an existing list, use list.Add with an array or list as the argument, and set the EXTRACT keyword. By default, elements are inserted at the end of the list; include the Index argument to specify where in the list the new elements should be inserted:

list.Add, array, /EXTRACT
list.Add, otherList, /EXTRACT
list.Add, otherList, Index, /EXTRACT

For example:

list.Add, [2,3,6,8], /EXTRACT

inserts four integers at the end of list.

Similarly, to insert the values from another list at the beginning of the target list:

subList = LIST('zero', 1, 2.0)
list.Add, subList, 0, /EXTRACT

Here, the string 'zero', the integer 1, and the floating point number 2.0 are inserted into list as the first three elements.

Change the Value of Multiple Elements

Change the value of multiple list elements in a single operation by specifying the indices to be replaced in the existing list and providing the replacement values in an array or another list:

list[[Index1, Index2, ..., Indexn]] = otherList
 
list[minIndex:maxIndex] = otherList
 
list[minIndex:maxIndex:stride] = otherList

Note that the expressions on the left and right sides of the equals sign must specify the same number of elements.

You can also assign multiple elements to the same value be using a scalar on the right hand side.

Copy a List

To copy a list reference, assign it to a new variable:

newList = origList

It is important to understand that with this operation, newList and origList are references to the same list; modifying an element in one list modifies the same element in the other list. For example, if we create list2 as a copy of list1 and then change the value of an element in list2, the same element in list1 also changes:

list1 = LIST('zero', 1, 2.0)
list2 = list1
list2[0] = 0L
HELP, list1[0], list2[0]

IDL Prints:

<Expression>    LONG      =  0
<Expression>    LONG      =  0

Note that both lists contain the new value for the first element.

To create a new list variable whose elements are copies of the values in the original list, use array syntax to copy all of the elements of the original list:

newList = origList[*]

For example:

list1 = LIST('zero', 1, 2.0)
list2 = list1[*]
list2[0] = 0l
HELP, list1[0], list2[0]

IDL Prints:

<Expression>    STRING    = 'zero'
<Expression>    LONG      =  0

Note that the value in list1 remains unchanged.

Iterate Through a List

To iterate through the elements in a list, use a loop and standard array syntax to index each list element:

FOR i = 0, N_ELEMENTS(list)-1 DO BEGIN
   ; do something with each element
   PRINT, list[i]
ENDFOR

For example:

list = LIST('zero', 1, 2.0)
FOR i=0, N_ELEMENTS(list)-1 DO PRINT, list[i]

 

You may also use FOREACH to iterate over the list elements:

list = LIST(77.97, 'Galactic', [2, 7, 1, 8, 2])
FOREACH element, list DO BEGIN
   PRINT, 'Element = ', element
ENDFOREACH

Note: While iterating through a list Avoid adding or removing elements. If the list is changed during the FOREACH, the behavior is undefined.

The 3 argument FOREACH loop will also work, if you want the current index:

list = LIST(77.97, 'Galactic', [2, 7, 1, 8, 2])
FOREACH element, list, index DO BEGIN
   HELP, index, element
ENDFOREACH

Access and Change Array Elements within a List

If a list item contains an array, another list, or a hash, individual elements within that item may be accessed and modified using standard array syntax. In this case, the first dimension must be a scalar that specifies the list element, and the higher dimensions are used to index into the array itself. The higher dimensions may be any combination of scalars, subscript ranges, or index arrays. The syntax looks like:

values = list[index, sub0, sub1,...]
list[index, sub0, sub1,...] = values

where index is a scalar that specifies the list element, and sub0, sub1,... are the subscript ranges or indices for the contained array.

For example, to create a "ragged" array, where each element is a vector of a different length:

list = LIST( FINDGEN(100), FINDGEN(67), FINDGEN(93), FINDGEN(120) )
 
; Print the 6th element of the first vector
print, list[0, 5]
 
; Print every other element of the 3rd vector
print, list[2, 0:*:2]
 
; Change several elements of the 4th vector
list[3, [5,10,15,20]] = -1

In this example, we create a list that contains some strings and a two-dimensional array:

list = LIST( 'Sensor Data', 'April 1, 2001', HANNING(100, 50) )
 
; Modify the element in the center of the array
list[2, 50, 25] = 0.0
 
; Change an entire column of the array
list[2, 99, *] = -1.0
 
; Extract a subset of the array
help, list[2, 10:15, 7:11]

IDL prints:

<Expression>    FLOAT     = Array[6, 5]

In this example, we create a list that contains another list (which contains an array) and a hash:

list = LIST( 'Sensor Data', 'April 2', $
  LIST('MyData', DIST(20, 30)), $
  HASH('LINESTYLE', 3, 'THICK', 2) )
 
; Extract the entire array from the sub-list
help, list[2, 1]
 
; Extract a subset of the array within the sub-list
help, list[2, 1, 10:15, [20,21,22] ]
 
; Add a new key-value to the hash within the list
list[3, 'COLOR'] = 'blue'
 
; Extract a value from the hash
help, list[3, 'COLOR' ]

IDL prints:

<Expression>    FLOAT     = Array[20, 30]
<Expression>    FLOAT     = Array[6, 3]
<Expression>    STRING    = 'blue'

Note: When indexing into an array contained within a list, the first dimension must always be the index of the list element. Since IDL can only handle a maximum of eight dimensions, you can only use up to seven dimensions when indexing into an array within a list. If the array is contained within a list (which is itself contained within a list), the maximum number of dimensions will be six, and so on.

Information about Lists


Logical Truth

The logical truth operator evaluates a list. It returns a value of 1 (TRUE) if the list is non-empty, and returns 0 (FALSE) if the list is empty.

IF (list) THEN . . .

Logical Negation

The logical negation operator negates the logical value of a list:

IF (~list) THEN . . .

If list is TRUE, the statement evaluates as FALSE, and so on.

N_ELEMENTS

The N_ELEMENTS function returns the number of elements in a list:

Result = N_ELEMENTS(list)

If list contains zero elements, or if list is an undefined variable, 0 is returned.

For more information, see N_ELEMENTS.

ISA

The ISA function can determine whether the given variable is a list:

x = LIST('apple', 99, 57.3)
PRINT, ISA(x, 'LIST')

IDL prints:

1

For more information, see ISA.

TYPENAME

The TYPENAME function returns the type LIST for a list variable:

x = LIST(1, 'hello', 5.0)
PRINT, TYPENAME(x)

IDL prints:

LIST

For more information, see TYPENAME.

HELP

The HELP procedure provides general information about a list variable:

newList = LIST('apple', 99, 27.3, [10, 20, 30])
HELP, newList

IDL prints:

NEWLIST         LIST  <LIST  ID=1  NELEMENTS=4>

In this case, the variable name is NEWLIST, the type name is LIST, the heap ID is 1, and there are four elements in the list.

PRINT

The PRINT procedure gives the value for each list element:

newList = LIST('apple', 99, 27.3, [10, 20, 30])
PRINT, newList

IDL prints:

apple
      99
      27.3000
      10      20      30

Implied Print

Using Implied Print with a list will print out each element in standard JSON notation:

IDL> newList = LIST('apple', 99, 27.3, [10, 20, 30])
IDL> newList

IDL prints:

[
  "apple",
  99,
  27.299999,
  [
    10,
    20,
    30
  ]
]

Tip: You can also output a list in YAML notation using YAML_SERIALIZE.

Version History


8.0

Introduced

8.1

Added NO_COPY keyword to the ToArray method

Added ability to index into arrays within a list

Added Count, FindValue, IsEmpty methods

8.2 Added the Where method, deprecated the FindValue method
8.2.3 Added DIMENSION keyword to the ToArray method
8.3 Added Move and Swap methods, added Implied Print to JSON format
8.4

Added Filter, Map, NestedMap, Reduce, and Sort methods.

Added PROMOTE_TYPE keyword to the ToArray method.

8.8.1

Ported from PRO code to C++ for performance.

See Also


!NULL, DICTIONARY, HASH, ORDEREDHASH, Logical Operators, Relational Operators, LAMBDA