Data Structures: Difference between revisions

From Kolmafia
Jump to navigation Jump to search
imported>Dj d
Created page with 'Most of this information was copied directly from ASH Maps Tutorial, by Veracity (http://kolmafia.sourceforge.net/advanced.html#maps) A map is indexed by one data type (the…'
 
imported>Dj d
No edit summary
Line 2: Line 2:
(http://kolmafia.sourceforge.net/advanced.html#maps)
(http://kolmafia.sourceforge.net/advanced.html#maps)


    A map is indexed by one data type (the key) and associates that key with another (or the same) data type (the value). The key can be any ASH simple data type: boolean, int, float, string, item, zodiac, location, class, stat, skill, effect, familiar, slot, or monster. The value can be any of those or can be an aggregate: another map. This effectively allows multi-dimensional maps and. In fact, that's how the syntax we provide for multi-dimensional aggregates actually operates: maps of maps of maps ...
A map is indexed by one data type (the key) and associates that key with another (or the same) data type (the value). The key can be any ASH simple data type: boolean, int, float, string, item, zodiac, location, class, stat, skill, effect, familiar, slot, or monster. The value can be any of those or can be an aggregate: another map. This effectively allows multi-dimensional maps and. In fact, that's how the syntax we provide for multi-dimensional aggregates actually operates: maps of maps of maps ...


    You can declare a map any time you can declare a variable: as a top level (global) variable, as a function parameter, or as a local variable in any scope.
You can declare a map any time you can declare a variable: as a top level (global) variable, as a function parameter, or as a local variable in any scope.


    You can fetch data from a map any time you can provide a data value: in an expression, as a function parameter, on the right side of an assignment statement, from a "return" statement, as so on. You can pass around entire maps, individual elements, or intermediate maps: "slices".
You can fetch data from a map any time you can provide a data value: in an expression, as a function parameter, on the right side of an assignment statement, from a "return" statement, as so on. You can pass around entire maps, individual elements, or intermediate maps: "slices".


    If you use a map on the left side of an assignment, you set the whole map at once to the new value. If you specify a map and a complete set of indices (of the correct types) on the left side of an assignment statement, you set a single element. If you specify a map and a prefix of indices (of the correct type), you directly set one of the intermediate maps, a "slice".
If you use a map on the left side of an assignment, you set the whole map at once to the new value. If you specify a map and a complete set of indices (of the correct types) on the left side of an assignment statement, you set a single element. If you specify a map and a prefix of indices (of the correct type), you directly set one of the intermediate maps, a "slice".


    The syntax for declaring the data type of a map:
The syntax for declaring the data type of a map:


        <data type> [ <key type>, ... ]   
    <data type> [ <key type>, ... ]   


    The syntax for referencing an element (or slice) of a map:
The syntax for referencing an element (or slice) of a map:


        <variablename>[ <key expression>, ... ]   
    <variablename>[ <key expression>, ... ]   


    All the key expressions will be evaluated at run time. If you specify all the keys the map expects, you fetch data of the type specified by the map. If you specify fewer keys than the map expects, you get an intermediate map, a "slice".
All the key expressions will be evaluated at run time. If you specify all the keys the map expects, you fetch data of the type specified by the map. If you specify fewer keys than the map expects, you get an intermediate map, a "slice".


    As an example:
As an example:


        boolean [string, string] props;   
    boolean [string, string] props;   


    might be used to hold "properties" associated with names.
might be used to hold "properties" associated with names.


        props[ "dog", "mammal" ] = true; props[ "dog", "pet" ] = true; props[ "dog", "fun" ] = false; props[ "turtle", "mammal" ] = false; props[ "turtle", "pet" ] = true; props[ "turtle", "fun" ] = false; props[ "aardvark", "mammal" ] = true; props[ "aardvark", "pet" ] = false; props[ "aardvark", "fun" ] = true;   
    props[ "dog", "mammal" ] = true; props[ "dog", "pet" ] = true; props[ "dog", "fun" ] = false; props[ "turtle", "mammal" ] = false; props[ "turtle", "pet" ] = true; props[ "turtle", "fun" ] = false; props[ "aardvark", "mammal" ] = true; props[ "aardvark", "pet" ] = false; props[ "aardvark", "fun" ] = true;   


    references:
references:


        props[ "dog", "mammal"] => true boolean [string] animal = props[ "turtle" ]; animal[ "fun" ] => false   
    props[ "dog", "mammal"] => true boolean [string] animal = props[ "turtle" ]; animal[ "fun" ] => false   


    You can test the presence of a key in a map using the "contains" operator:
You can test the presence of a key in a map using the "contains" operator:


        <aggregate reference expression> contains <key expression>   
    <aggregate reference expression> contains <key expression>   


    Where <aggregate reference expression> must evaluate at run time to a map or slice, and must evaluate at run time to a key of the appropriate type. (Note that that is enforced at parse time; ASH can tell the datatype any expression will produce).
Where <aggregate reference expression> must evaluate at run time to a map or slice, and must evaluate at run time to a key of the appropriate type. (Note that that is enforced at parse time; ASH can tell the datatype any expression will produce).


        props contains "dog" => true props contains "elephant" => false props[ "aardvark" ] contains "fun" => true animal contains "pet" => true animal contains "favorite food" => false   
    props contains "dog" => true props contains "elephant" => false props[ "aardvark" ] contains "fun" => true animal contains "pet" => true animal contains "favorite food" => false   


    You can remove a key-value association from a map using the "remove" unary operator:
You can remove a key-value association from a map using the "remove" unary operator:


        remove <aggregate reference>   
    remove <aggregate reference>   


    For clarification, an aggregate reference is "<map name>[ <index 1> ... <index n> ]" where <map name>[ <index 1> ... <index n-1> ] specifies the "slice" and <index n> specifies the "key". Which is just what you expect, if you fully specify the indices; for a single dimensional map, "map[10]" -> "map" is the slice and 10 is the key. The "remove" operator removes the "key" from the "slice". For example:
For clarification, an aggregate reference is "<map name>[ <index 1> ... <index n> ]" where <map name>[ <index 1> ... <index n-1> ] specifies the "slice" and <index n> specifies the "key". Which is just what you expect, if you fully specify the indices; for a single dimensional map, "map[10]" -> "map" is the slice and 10 is the key. The "remove" operator removes the "key" from the "slice". For example:


        string [int] map1; map1[5] = "foo"; print( count( map1 ) + " " + map1 contains 5 + " " + map1[5] ); print( "remove: " + remove map1[5] ); print( count( map1 ) + " " + map1 contains 5 + " " + map1[5] ); print( "remove: " + remove map1[5] ); int [string, string] map2; map2["me","you"] = 17; print( count( map2["me"] ) + " " + map2["me"] contains "you" + " " + map2["me","you"] ); print( "remove: " + remove map2["me", "you"] ); print( count( map2["me"] ) + " " + map2["me"] contains "you" + " " + map2["me","you"] ); print( "remove: " + remove map2["me", "you"] ); print( count( map2 ) + " " + map2["me"] ); print( "remove: " + remove map2["me"] ); print( count( map2 ) + " " + map2["me"] );   
    string [int] map1; map1[5] = "foo"; print( count( map1 ) + " " + map1 contains 5 + " " + map1[5] ); print( "remove: " + remove map1[5] ); print( count( map1 ) + " " + map1 contains 5 + " " + map1[5] ); print( "remove: " + remove map1[5] ); int [string, string] map2; map2["me","you"] = 17; print( count( map2["me"] ) + " " + map2["me"] contains "you" + " " + map2["me","you"] ); print( "remove: " + remove map2["me", "you"] ); print( count( map2["me"] ) + " " + map2["me"] contains "you" + " " + map2["me","you"] ); print( "remove: " + remove map2["me", "you"] ); print( count( map2 ) + " " + map2["me"] ); print( "remove: " + remove map2["me"] ); print( count( map2 ) + " " + map2["me"] );   


    yields:
yields:


        1 true foo remove: foo 0 false remove: 1 true 17 remove: 17 0 false 0 remove: 0 1 aggregate int [string] remove: aggregate int [string] 0 aggregate int [string]
    1 true foo remove: foo 0 false remove: 1 true 17 remove: 17 0 false 0 remove: 0 1 aggregate int [string] remove: aggregate int [string] 0 aggregate int [string]

Revision as of 14:21, 4 October 2009

Most of this information was copied directly from ASH Maps Tutorial, by Veracity (http://kolmafia.sourceforge.net/advanced.html#maps)

A map is indexed by one data type (the key) and associates that key with another (or the same) data type (the value). The key can be any ASH simple data type: boolean, int, float, string, item, zodiac, location, class, stat, skill, effect, familiar, slot, or monster. The value can be any of those or can be an aggregate: another map. This effectively allows multi-dimensional maps and. In fact, that's how the syntax we provide for multi-dimensional aggregates actually operates: maps of maps of maps ...

You can declare a map any time you can declare a variable: as a top level (global) variable, as a function parameter, or as a local variable in any scope.

You can fetch data from a map any time you can provide a data value: in an expression, as a function parameter, on the right side of an assignment statement, from a "return" statement, as so on. You can pass around entire maps, individual elements, or intermediate maps: "slices".

If you use a map on the left side of an assignment, you set the whole map at once to the new value. If you specify a map and a complete set of indices (of the correct types) on the left side of an assignment statement, you set a single element. If you specify a map and a prefix of indices (of the correct type), you directly set one of the intermediate maps, a "slice".

The syntax for declaring the data type of a map:

    [ <key type>, ... ]  

The syntax for referencing an element (or slice) of a map:

   <variablename>[ <key expression>, ... ]  

All the key expressions will be evaluated at run time. If you specify all the keys the map expects, you fetch data of the type specified by the map. If you specify fewer keys than the map expects, you get an intermediate map, a "slice".

As an example:

   boolean [string, string] props;  

might be used to hold "properties" associated with names.

   props[ "dog", "mammal" ] = true; props[ "dog", "pet" ] = true; props[ "dog", "fun" ] = false; props[ "turtle", "mammal" ] = false; props[ "turtle", "pet" ] = true; props[ "turtle", "fun" ] = false; props[ "aardvark", "mammal" ] = true; props[ "aardvark", "pet" ] = false; props[ "aardvark", "fun" ] = true;  

references:

   props[ "dog", "mammal"] => true boolean [string] animal = props[ "turtle" ]; animal[ "fun" ] => false  

You can test the presence of a key in a map using the "contains" operator:

   <aggregate reference expression> contains <key expression>  

Where <aggregate reference expression> must evaluate at run time to a map or slice, and must evaluate at run time to a key of the appropriate type. (Note that that is enforced at parse time; ASH can tell the datatype any expression will produce).

   props contains "dog" => true props contains "elephant" => false props[ "aardvark" ] contains "fun" => true animal contains "pet" => true animal contains "favorite food" => false  

You can remove a key-value association from a map using the "remove" unary operator:

   remove <aggregate reference>  

For clarification, an aggregate reference is "<map name>[ <index 1> ... <index n> ]" where <map name>[ <index 1> ... <index n-1> ] specifies the "slice" and <index n> specifies the "key". Which is just what you expect, if you fully specify the indices; for a single dimensional map, "map[10]" -> "map" is the slice and 10 is the key. The "remove" operator removes the "key" from the "slice". For example:

   string [int] map1; map1[5] = "foo"; print( count( map1 ) + " " + map1 contains 5 + " " + map1[5] ); print( "remove: " + remove map1[5] ); print( count( map1 ) + " " + map1 contains 5 + " " + map1[5] ); print( "remove: " + remove map1[5] ); int [string, string] map2; map2["me","you"] = 17; print( count( map2["me"] ) + " " + map2["me"] contains "you" + " " + map2["me","you"] ); print( "remove: " + remove map2["me", "you"] ); print( count( map2["me"] ) + " " + map2["me"] contains "you" + " " + map2["me","you"] ); print( "remove: " + remove map2["me", "you"] ); print( count( map2 ) + " " + map2["me"] ); print( "remove: " + remove map2["me"] ); print( count( map2 ) + " " + map2["me"] );  

yields:

   1 true foo remove: foo 0 false remove: 1 true 17 remove: 17 0 false 0 remove: 0 1 aggregate int [string] remove: aggregate int [string] 0 aggregate int [string]