The HASH function creates a new hash. A hash is a compound data type that contains key-value pairs of different data types, including any mixture of scalars, arrays, structures, pointers, object references, lists, and other hashes.
Hashes have the following properties:
Note: While you can use IDL's array syntax to access elements in a hash, it is important to remember that a hash does not behave like an array in all cases. See below for a full description of the characteristics of a hash.
Result = HASH( [Key1, Value1, Key2, Value2, ... Keyn, Valuen] [, /EXTRACT] [, /NO_COPY] )
or
Result = HASH( Keys, Values [, /EXTRACT] )
or
Result = HASH( Keys )
or
Result = HASH( Structure [, /EXTRACT] )
Returns a reference to a newly-created hash.
Each Key argument can be a scalar string or number. The corresponding Value can be a scalar or array of any IDL data type including !NULL.
Each Key argument can also be an array or list, in which case the corresponding Value must be a scalar, an array or a list. If Value is a scalar, then that value is copied into every key. Otherwise, if Value is an array or a list, it must contain the same number of elements as the keys. In this case each element of the Key and Value is inserted as a separate key-value pair. If a given key occurs more than once within the input arguments, the last value will be retained.
If only Keys is supplied (as either a scalar, an array, or a list), then the corresponding values will be set to the default value of !NULL.
If no keys or values are supplied, an empty hash is returned.
Note: For strings, the key is case sensitive. For example, "Abc" and "abc" will be considered as two separate keys. For numbers, the actual data type does not matter, only the numeric value is used. For example, 1b (byte), 1 (int), and 1.0 (float) will all equate to the same key. Note however that because of the precision of floating-point arithmetic, single-precision and double-precision keys may be considered as different numbers. For example, 0.1 (float) and 0.1d (double) will not equate to the same key.
Each Value argument can be a variable or expression of any IDL data type including !NULL.
Instead of passing in keys or values, a single IDL structure may be passed in. In this case, each tag/value pair within the structure will be inserted within the hash.
By default, all values are put into the hash unchanged. If the EXTRACT keyword is set, then any structures (or substructures) will be converted into hashes before being inserted.
If the NO_COPY keyword is set, the value data is taken away from the Value variable and attached directly to the hash variable. The default behavior is to make a copy of the input values.
hash=HASH("one", 1.0, "blue", [255,0,0], "Pi", !DPI)
PRINT, N_ELEMENTS(hash)
IDL Prints:
3
hash = HASH(80301, 'Boulder', 'Joe', 48236)
PRINT, hash[80301]
PRINT, hash['Joe']
IDL Prints:
Boulder
48236
keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
values = LIST('one', 2.0, 3, 4l, PTR_NEW(5), {n:6}, COMPLEX(7,0))
hash = HASH(keys, values)
PRINT, N_ELEMENTS(hash)
IDL Prints:
7
struct = {FIELD1: 4.0, FIELD2: {SUBFIELD1: "hello", SUBFIELD2: 3.14}}
hash = HASH(struct, /EXTRACT)
PRINT, hash
PRINT, hash['FIELD2']
IDL Prints:
FIELD2: <ObjHeapVar3374(HASH)>
FIELD1: 4.00000
SUBFIELD1: hello
SUBFIELD2: 3.14000
The Hash::Count function method returns the number of elements in the hash. Optionally, the Hash::Count method can return the number of matches to a given value.
Result = hash.Count( [Value] )
By default, returns an integer containing the number of elements in the hash. If Value is supplied, then returns an integer giving the number of occurrences of Value within the hash.
Note: See the Hash::Where method for the rules that are used for comparing values.
A value to search for within the hash.
None
The Hash::HasKey function method tests whether a key or set of keys exists in a hash.
Result = hash.HasKey(Keys )
If Keys is a scalar, then returns a scalar 1 if the key exists in the hash, or a 0 otherwise. If Keys is an array or list, then returns an array of 0's or 1's.
A scalar key, or an array or list of keys.
None.
hash = HASH('black', 0, 'gray', 128, 'grey', 128, 'white', 255)
print, hash.HasKey('gray')
print, hash.HasKey(['grey','red','white'])
IDL Prints:
1
1 0 1
The Hash::IsEmpty function method tests whether the hash is empty or not.
Result = hash.IsEmpty( )
Returns 1 if the hash contains zero elements, and 0 otherwise.
None.
None.
The Hash::Keys function method returns a list containing all keys in a hash. The order of key/value pairs within hash.Keys() and hash.Values() is guaranteed to remain the same as long as no items are added or removed from the hash.
Result = hash.Keys( )
Returns a list containing all of the keys. If the hash is empty then an empty list is returned.
None.
None.
hash = HASH('black', 0, 'gray', 128, 'grey', 128, 'white', 255)
list = hash.Keys()
print, list
IDL Prints:
white
black
gray
grey
The Hash::Remove method removes elements from a hash and optionally returns the removed value.
hash.Remove [, Keys] [, /ALL]
or
Result = hash.Remove( [, Keys] [, /ALL] )
If Keys is a scalar, then the result is the value itself. If Keys is an array or list of keys, then the result is a hash containing the removed key-value pairs.
Note: If the hash is empty, calling the Hash::Remove() function method will throw an error. The Hash::Remove procedure method will quietly return.
A scalar key or an array or list of keys to be removed. If no Keys are supplied, an arbitrarily-chosen element is removed.
Set this keyword to remove all entries in Hash, leaving the hash empty, but still in existence.
Create a hash and print its contents:
hash = HASH("one", 1.0, "blue", [255,0,0], "Pi", !DPI)
PRINT, hash
IDL Prints:
Pi, 3.141592798.6
blue, 255 0 0
one, 1.00000
Now delete some hash elements and print the contents again:
hash.Remove, ["one", "Pi"]
PRINT, hash
PRINT, N_ELEMENTS(hash)
IDL Prints:
blue, 255 0 0
1
Now remove the last element off the hash, printing the removed value:
PRINT, hash.Remove()
IDL Prints:
255 0 0
The Hash::ToStruct function method returns an IDL structure containing all of the hash elements converted into tag/value pairs. Keys which are not strings will not be included in the structure. For string keys, any special characters in the string will be converted to underscores to produce a valid IDL tag name. If a value is undefined (!NULL) it will also be skipped (unless the MISSING keyword is set).
Note: Since the hash stores its key/value pairs in an arbitrary order, the order of tags within the resulting structure will also be arbitrary, even if the same structure was used to create the hash.
Result = hash.ToStruct( [, MISSING=value] [, /NO_COPY] [, /RECURSIVE] [, SKIPPED=variable] )
The result is an IDL structure containing the key/value pairs. If the hash is empty or contains no valid keys then !NULL is returned.
None.
Set this keyword to the value to be returned for missing (!NULL) values. The default behavior of the Hash::ToStruct method is to skip any keys whose value is !NULL.
Set this keyword to move each element from the hash to the output structure. When finished, the hash will be empty.
If this keyword is set, then any HASH values within the structure are also converted into structures using the ToStruct() method. The MISSING, NO_COPY, and RECURSIVE keywords are passed on to the recursive ToStruct() calls.
Set this keyword to a named variable in which to return a variable of type LIST containing all of the skipped keys. A key will be skipped (not included in the result structure) under the following circumstances:
hash = HASH('black', 0, 'gray', 128, 'grey', 128, 'white', 255, 'light red', 200)
HELP, hash.ToStruct()
IDL Prints:
** Structure <332a8ca8>, 5 tags, length=10, data length=10, refs=1:
LIGHT_RED INT 200
WHITE INT 255
BLACK INT 0
GRAY INT 128
GREY INT 128
An example using the RECURSIVE keyword:
struct = {FIELD1: 4.0, FIELD2: {SUBFIELD1: "hello", SUBFIELD2: 3.14}}
hash = HASH(struct, /EXTRACT)
PRINT, hash
PRINT, hash['FIELD2']
IDL Prints:
FIELD2: <ObjHeapVar3374(HASH)>
FIELD1: 4.00000
SUBFIELD1: hello
SUBFIELD2: 3.14000
The Hash::Values function method returns a list containing all values in a hash.The order of key/value pairs within hash.Keys() and hash.Values() is guaranteed to remain the same as long as no items are added or removed from the hash.
Result = hash.Values( )
Returns a list containing all of the values. If the hash is empty then an empty list is returned.
None.
None.
hash = HASH('black', 0, 'gray', 128, 'grey', 128, 'white', 255)
list = hash.Values()
print, list
IDL Prints:
255
0
128
128
The Hash::Where function method returns a list of all keys that contain a certain value.
Note: This method returns a result that is equivalent to using the EQ operator, but also provides additional keywords that are not available with the operator.
Result = hash.Where( Value [, COMPLEMENT=variable] [, COUNT=variable] [, NCOMPLEMENT=variable] )
Returns a list containing all of the keys that contain the value. If there are no matches, an empty list is returned. The following rules are used when comparing values:
A variable or expression of any IDL data type, including !NULL.
Set this keyword to a named variable that will return a list of keys that do not contain the value.
Note: If Value is another hash, the COMPLEMENT is a list containing all of the keys in both hashes that either do not exist in the other hash, or have a different value. In this case the number of keys in the COMPLEMENT may be greater than the number of keys in either original hash.
Set this keyword to a named variable that will return the number of matches.
Set this keyword to a named variable that will return the number of keys within the COMPLEMENT list.
The following example generates a random integer and an array of ten random integers (both between 0 and 9). The sample uses Hash::Where to determine if there are any matches of the value in the hash (the hash keys are the array indices).
keys = 'key' + STRTRIM(SINDGEN(10),2)
rndmVal = FIX(10 * RANDOMU(seed, 1))
rndmArr = FIX(10 * RANDOMU(seed, 10))
h = HASH(keys, rndmArr)
matches = h.Where(rndmVal)
PRINT, 'Random value = ', rndmVal
PRINT, 'Random array = ', rndmArr
HELP, matches
PRINT, 'Matching keys: ', matches, FORMAT=('(A)')
Sample output:
Random value = 8
Random array = 2 7 8 8 0 4 8 3 7 1
Matching keys:
key3
key2
key6
To combine two hashes to make a new hash, use the + operator:
hash1 = HASH('key1', 1, 'key2', 2, 'keydup', 'abc')
hash2 = HASH('key3', 'three', 'key4', 4.0, 'keydup', 'xyz')
hash3 = hash1 + hash2
PRINT, hash3
IDL Prints:
keydup, xyz
key2, 2
key1, 1
key4, 4.00000
key3, three
Note: If the two hashes have duplicate keys, the values will be taken from the second operand.
The + operator may also be used to combine a hash and an IDL structure to make a new hash:
hash1 = HASH('key1', 1, 'key2', 2, 'keydup', 'abc')
struct = {tag1: 'mytagvalue', tag2: 2.0}
hash3 = hash1 + struct
PRINT, hash3
IDL Prints:
keydup: abc
key2: 2
key1: 1
TAG2: 2.00000
TAG1: mytagvalue
The EQ operator does a comparison of two hashes, or a hash and a value. For the case of two hashes, EQ returns a list of keys that exist in both hashes and have the same value. For the case of a hash and a value, EQ returns a list of keys that contain that value. In either case, if there are no matches, an empty list is returned.
For example, to compare two hashes:
hash1 = HASH('key1', 1, 'key2', 2, 'key3', 3, 'anotherkey', 3.14)
hash2 = HASH('key1', 1, 'key2', 2, 'key3', 3.5)
result = hash1 EQ hash2
HELP, result
PRINT, result
IDL Prints:
RESULT LIST <ID=114775 NELEMENTS=2>
key2
key1
To compare a hash and a value:
hash = HASH('key1', 1.414, 'key2', 3.14, 'key3', 1.414)
result = hash EQ 1.414 ; (or 1.414 EQ hash)
HELP, result
PRINT, result
IDL Prints:
RESULT LIST <ID=114789 NELEMENTS=2>
key1
key3
To compare a hash and a value that is not in the hash:
hash = HASH('key1', 1.414, 'key2', 3.14, 'key3', 1.414)
result = hash EQ 2.718 ; (or 2.718 EQ hash)
HELP, result
IDL Prints:
RESULT LIST <ID=114817 NELEMENTS=0>
Note: See the Hash::Where method for the rules that are used for comparing values.
The NE operator behaves in the opposite manner of EQ. For NE with two hashes, the result is a list containing all of the keys in both hashes that either do not exist in the other hash, or have a different value. For NE with a hash and a value, the result is a list containing all of the keys that do not contain that value. In either case, if every element is a match, then an empty list is returned.
For example, to compare two hashes:
hash1 = HASH('key1', 1, 'key2', 2, 'key3', 3, 'anotherkey', 3.14)
hash2 = HASH('key1', 1, 'key2', 2, 'key3', 3.5)
result = hash1 NE hash2
HELP, result
PRINT, result
IDL Prints:
RESULT LIST <ID=114843 NELEMENTS=2>
anotherkey
key3
To compare a hash and a value:
hash = HASH('key1', 1.414, 'key2', 3.14, 'key3', 1.414)
result = hash NE 1.414 ; (or 1.414 NE hash)
HELP, result
PRINT, result
IDL Prints:
RESULT LIST <ID=114857 NELEMENTS=1>
key2
To compare a hash and a !NULL value:
hash = HASH('key1', 1.414, 'key2', 3.14, 'key3', !NULL, 'key4', !NULL)
result = hash NE !NULL ; (or !NULL NE hash)
HELP, result
PRINT, result
IDL Prints:
RESULT LIST <ID=114817 NELEMENTS=2>
key2
key1
In many cases, you can access elements of a hash variable using standard IDL array syntax, as if the hash were a one-dimensional array.
To copy the value of a single hash element into a new variable, leaving the hash unchanged, use array syntax:
value = hash[Key]
where Key is the scalar key of the desired element within the hash.
To retrieve an arbitrary element in a hash and remove it, use the hash.Remove() method:
value = hash.Remove()
To retrieve a specific element in a hash and remove it:
value = hash.Remove(Key)
where Key is the scalar key of the desired element within the hash.
To insert a single value into a hash, creating a new hash element, use array syntax:
hash[Key] = Value
where Value is the value to be stored in the new hash element.
To change the value of a single hash element, use array syntax:
hash[Key] = Value
where Key is the scalar key of the desired element within the hash and Value is the new value.
To create a new hash that is a subset of an existing hash, use array syntax:
newHash = origHash[ [Key1, ..., Keyn] ]
or
newHash = origHash[ Keys ]
where Key1,..., Keyn are individual keys concatenated into an array, and Keys is an array or list of keys. Here newHash is a new hash variable that contains copies of the key-value pairs from origHash specified by the keys.
Insert or change the value of multiple hash elements in a single operation by specifying an array or list of keys to be replaced and/or added in the existing hash and providing the replacement values in an array or list:
hash[[Key1, ..., Keyn]] = Values
or
hash[ Keys ] = Values
where Key1,..., Keyn are individual keys concatenated into an array, Keys is an array or list of keys, and Values is a scalar, an array or a list of values. If Values is a scalar, then that value is copied into every key. Otherwise, if Values is an array or a list, it must contain the same number of elements as the keys. In this case each element of Keys and Values is inserted as a separate key-value pair. For each key-value pair, if the key already exists in the hash then the value is replaced, and if the key does not exist then it is added. If a given key occurs more than once within the new keys, the last value will be retained.
To copy a hash reference, simply assign it to a new variable:
newHash = origHash
It is important to understand that with this operation, newHash and origHash are references to the same hash; modifying an element in one hash modifies the same element in the other hash. For example, if we create hash2 as a copy of hash1 and then change the value of an element in hash2, the same element in hash1 also changes:
hash1 = HASH('key1', 1, 'key2', 2)
hash2 = hash1
hash2['key1'] = 'hello'
HELP, hash1['key1'], hash2['key2']
IDL Prints:
<Expression> STRING = 'hello'
<Expression> STRING = 'hello'
Note that both hashes contain the new value for that key.
To create a new hash variable whose elements are copies of the values in the original hash, you could use the following:
newHash = HASH(origHash.Keys(), origHash.Values())
Another method to copy a hash is to use array syntax to copy all of the elements:
newHash = origHash[*]
This is equivalent to using HASH(origHash.Keys(), origHash.Values()) and is provided as a programming shortcut.
For example:
hash1 = HASH('key1', 1, 'key2', 2)
hash2 = hash1[*]
hash2['key1'] = 'hello'
HELP, hash1['key1'], hash2['key2']
IDL Prints:
<Expression> STRING = 1
<Expression> STRING = 'hello'
Note that the value in hash1 remains unchanged.
To iterate through the elements in a hash, loop over the keys and use standard array syntax:
hash = HASH('Mercury', 1, 'Venus', 2, 'Earth', 3, 'Mars', 4)
keys = hash.Keys()
FOR i=0,N_ELEMENTS(hash)-1 DO PRINT, hash[keys[i]]
A more efficient method of iteration is to use FOREACH:
hash = HASH('Mercury', 1, 'Venus', 2, 'Earth', 3, 'Mars', 4)
FOREACH value, hash DO PRINT, 'Value = ', value
You may also use the optional argument to FOREACH to retrieve the key associated with each value:
hash = HASH('Mercury', 1, 'Venus', 2, 'Earth', 3, 'Mars', 4)
FOREACH value, hash, key DO PRINT, key + ' is planet #', value
If a hash item contains an array, another hash, or a list, individual elements within that item may be accessed and modified using standard array syntax. In this case, the first dimension must be a hash key (a scalar string or number) that specifies the hash 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 = hash[key, sub0, sub1,...]
hash[key, sub0, sub1,...] = values
where key is a scalar string or number that specifies the hash 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:
hash = HASH( 'Array1', FINDGEN(100), 'Array2', FINDGEN(67), 'Array3', FINDGEN(93), $
'Array4', FINDGEN(120) )
; Print the 6th element of the first vector
PRINT, hash['Array1', 5]
; Print every other element of the third vector
PRINT, hash['Array3', 0:*:2]
; Change several elements of the fourth vector
HASH['Array4', [5,10,15,20]] = -1
In this example, we create a hash that contains a one-dimensional array, a string, and a two-dimensional array:
hash = HASH( 'Data', FINDGEN(10), 'Date', 'April 1, 2001', 'Hanning', HANNING(100, 50) )
; Modify an element in the center of the 2D array
hash['Hanning', 50, 25] = 0.0
; Change an entire column of the 2D array
hash['Hanning', 99, *] = -1.0
; Extract a subset of the 2D array
HELP, hash['Hanning', 10:15, 7:11]
IDL prints:
<Expression> FLOAT = Array[6, 5]
In this example, we create a hash that contains a one-dimensional array, a string, a list, (which contains a two-dimensional array), and another hash:
hash = HASH('Data', FINDGEN(10), 'Date', 'April 2', $
'List', LIST('MyData', DIST(20, 30)), $
'Properties', HASH('LINESTYLE', 3, 'THICK', 2) )
; Extract the entire 2D array from the sub-list
HELP, hash['List', 1]
; Extract a subset of the 2D array within the sub-list
HELP, hash['List', 1, 10:15, [20,21,22] ]
; Add a new key-value to the hash within the hash
hash['Properties', 'COLOR'] = 'blue'
; Extract a value from the hash within the hash
HELP, HASH['Properties', '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 hash, the first dimension must always be the hash key. 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 hash. If the array is contained within a hash or list (which is itself contained within a hash), the maximum number of dimensions will be six, and so on.
The logical truth operator evaluates a hash. It returns a value of 1 (TRUE) if the hash is non-empty, and returns 0 (FALSE) if the hash is empty.
IF (hash) THEN . . .
The logical negation operator negates the logical value of a hash:
IF (~hash) THEN . . .
If hash is TRUE, the statement evaluates as FALSE, and so on.
The N_ELEMENTS function returns the number of elements in a hash:
Result = N_ELEMENTS(hash)
If hash contains zero elements, or if hash is an undefined variable, 0 is returned.
For more information, see N_ELEMENTS .
The ISA function can determine whether the given variable is a hash:
x = HASH('key1', 1, 'key2', 2)
PRINT, ISA(x, 'HASH')
IDL prints:
1
For more information, see ISA.
The TYPENAME function returns the type HASH for a hash variable:
x = HASH('key1', 1, 'key2', 2)
PRINT, TYPENAME(x)
IDL prints:
HASH
For more information, see TYPENAME.
The HELP procedure provides general information about a hash variable:
newHash = HASH('key1', 1, 'key2', [1,2,3])
HELP, newHash
IDL prints:
NEWHASH HASH <ID=1 NELEMENTS=2>
In this case, the variable name is NEWHASH. the type name is HASH, the heap ID is 1, and there are two elements in the hash.
The PRINT procedure gives the value for each hash element:
newHash = HASH('Mercury', 1, 'Venus', 2, 'Earth', 3, 'Mars', 4)
PRINT, newHash
IDL prints:
Earth, 3
Mars, 4
Venus, 2
Mercury, 1
8.0 |
Introduced |
8.1 |
Added NO_COPY keyword to ToStruct function method Added Count, FindValue, IsEmpty methods Added ability to index into arrays within a hash |
8.2 | Added the Where method, deprecated the FindValue method |