Maps

In use, maps are similar to Lists in that they can store a varying number of elements that are accessed by a value.

They differ in several ways. Map data types act as a lookup from one value (the key) to another. Values used as a key are not restricted to integers and do not have to be sequential. Keys and values can be of any valid FISH type. Like lists, maps are passed by value. Lastly, maps are dynamically sized.

See the Map Utilities for available methods that exist to create and manipulate map types.

Map types are created using the map intrinsic, as follows.

map1 = map

Maps can be assigned entries during creation by providing key/value pairs to the map intrinsic.

map1 = map(10,1.0,   'fred',4.0,   3.4,6.0)

The line above creates a map with three key/value pairs, one that maps the integer 10 to the value 1.0, one that maps the string fred to the value 4.0, and one that maps the real value 3.4 to the value 6.0.

Accessing a value given a key is done using the () operator, just like arrays.

v = map1('fred')

The line above returns the value 4.0 that was assigned to the key fred. Maps are implemented using a generalized sorted red-black tree container to optimize lookup times.

You can iterate through all the values of a map using the loop foreach statement. This will assign the loop variable sequentially to every value of the map.

loop foreach local v map1
   io.out(v)
endloop

You can also iterate through the keys of a map by using the map.keys intrinsic:

loop foreach local v map.keys(map1)
   io.out(string(v) + ' = ' + string(map1(v)))
endloop

Because maps are passed by value, assigning a map to another symbol creates a copy of the map, rather than having both symbols refer to the same array. For example,

local a = map(1,'fred',    5,'george')
local b = a
b(5) = 'mary'
io.out(a(5))
io.out(b(5))

will output ‘george’ then ‘mary’.

The following data file offers further examples of the use of maps in FISH.

fish define testBreak
    loop local i (1,2)
        testmap = map('first',1,  'second',2,  'third',3)
        sum = 0
        loop foreach local v testmap
            sum = sum + v
        endloop
    endloop        
end
[testBreak]
[sum]

fish define test1
    local temp = map('hello',1,'world',2)
    test1 = temp('hello') + temp('world')
end
[test1]

fish define test2
    testmap = map('first',1,'second',2,'third',3)
    map.remove(testmap,'first')
    map.add(testmap,'fourth',4)
    testmap('second')=8
    ; values are now fourth->4, second->8, third->3
    local output = 0
    loop foreach n testmap
        output = output + n
    endloop
    test2 = output
end
[test2]

fish define test3
    ; test keys
    testmap = map('yet',1,'another',4,'test',9,'m',16)
    testkeys = map.keys(testmap)
    test3 = testkeys(3)
    
    ; check has
    if (map.has(testmap,'wrongkey'))
      hascheck = 909
    else if (map.has(testmap,'another'))
      hascheck = testmap('another')
    endif
end
[test3]
[hascheck]

Maps are an iterable type. This means you can use it as the target of a loop foreach statement (see Loop ForEach and can be split (see Splitting). Each value of the map is iterated through in order.


As with most aggregate types, when the value is listed it will simply indicate that it is of type Map and the the number of entries. To see the contents of the map use the fish list contents command.