NB. [nested] map of (,: key;value) entries NB. NB. INSTALL NB. > copy map.ijs user/ NB. NB. RUN NB. require '~user/map.ijs' NB. coinsert 'map' NB. NB. NB. FLAT MAPS NB. NB. creating a map: NB. NB. MAP=: empty'' NB. you should've guessed! NB. MAP=: 1 2 3 'one' setmap empty'' NB. with some values NB. MAP=: ('k1';i.3),:('k2';'qq') NB. declaratively NB. +--+-----+ NB. |k1|0 1 2| NB. +--+-----+ NB. |k2|qq | NB. +--+-----+ NB. NB. changing values: NB. NB. MAP=: (i.3 4) 'k2' setmap MAP NB. similar to amend, "}" NB. +--+---------+ NB. |k1|0 1 2 | NB. +--+---------+ NB. |k2|0 1 2 3| NB. | |4 5 6 7| NB. | |8 9 10 11| NB. +--+---------+ NB. NB. adding values: NB. NB. MAP=: 'qq' 'k3' setmap MAP NB. same as setting NB. +--+---------+ NB. |k1|0 1 2 | NB. +--+---------+ NB. |k2|0 1 2 3| NB. | |4 5 6 7| NB. | |8 9 10 11| NB. +--+---------+ NB. |k3|qq | NB. +--+---------+ NB. NB. removing entries: NB. NB. i.e. setting to nothing NB. MAP=: 'k2' setmap MAP NB. graceful for missing keys NB. +--+---------+ NB. |k1|0 1 2 | NB. +--+---------+ NB. |k3|qq | NB. +--+---------+ NB. NB. getting values: NB. NB. similar to From '{' NB. VALUE=: 'k1' getmap MAP NB. missing keys gracefully return empty'' NB. 0 1 2 NB. NB. getmap MAP NB. catalog of keys, like '{' NB. +--+--+--+ NB. |k1|k2|k3| NB. +--+--+--+ NB. NB. index of the key: NB. NB. INDEX=: 'k4' ndxmap MAP NB. NB. existance of key: NB. NB. BOOL=: 'k4' hasmap MAP NB. NB. NB. NESTED MAPS NB. NB. build a nested map: NB. NB. MAPX=: 3 'k2.k6' setmapx 'val' 'k2.k4' setmapx 1 'k1.k3' setmapx empty'' NB. MAPX=: 3 'k2.k4.k8' setmapx (i.3 4) 'k1.k5' setmapx MAPX NB. +--+--------------+ NB. |k1|+--+---------+| NB. | ||k3|1 || NB. | |+--+---------+| NB. | ||k5|0 1 2 3|| NB. | || |4 5 6 7|| NB. | || |8 9 10 11|| NB. | |+--+---------+| NB. +--+--------------+ NB. |k2|+--+--------+ | NB. | ||k4|+--+---+| | NB. | || || |val|| | NB. | || |+--+---+| | NB. | || ||k8|3 || | NB. | || |+--+---+| | NB. | |+--+--------+ | NB. | ||k6|3 | | NB. | |+--+--------+ | NB. +--+--------------+ NB. NB. removing nested entries: NB. NB. i.e. setting to nothing NB. 'k1.k5' setmapx 'k2' setmapx MAPX NB. +--+------+ NB. |k1|+--+-+| NB. | ||k3|1|| NB. | |+--+-+| NB. +--+------+ NB. NB. value of deep key from nested map: NB. NB. 'k1.k3' getmapx MAPX NB. 1 NB. 'k2.k4' getmapx MAPX NB. +--+---+ NB. | |val| NB. +--+---+ NB. |k8|3 | NB. +--+---+ NB. 'k2.k4.' getmapx MAPX NB. val NB. NB. getmapx MAPX NB. catalog of nested keys, like '{' NB. +-----+-----+------+--------+-----+ NB. |k1.k3|k1.k5|k2.k4.|k2.k4.k8|k2.k6| NB. +-----+-----+------+--------+-----+ NB. NB. flatmap MAPX NB. covert nested map to flat NB. +--------+---------+ NB. like Spread 0 NB. |k1.k3 |1 | NB. +--------+---------+ NB. |k1.k5 |0 1 2 3| NB. | |4 5 6 7| NB. | |8 9 10 11| NB. +--------+---------+ NB. |k2.k4. |val | NB. +--------+---------+ NB. |k2.k4.k8|3 | NB. +--------+---------+ NB. |k2.k6 |3 | NB. +--------+---------+ NB. NB. MAPX -: flatmapx flatmap MAPX NB. reverse of flattening NB. 1 NB. NB. strmap MAPX NB. covert nested map to multiline string NB. k1.k3 1 NB. useful for storing and restoring config NB. k1.k5 i.3 4 NB. k2.k4. 'val' NB. k2.k4.k8 3 NB. k2.k6 3 NB. NB. MAPX -: strmapx strmap MAPX NB. reverse from string NB. 1 NB. NB. CMAP=: 0 : 0 NB. build nested map from COMPACT string NB. k1 .k3 1 .k5 i.3 4 NB. k2 .k4. 'val' .k4.k8 3 .k6 3 NB. ) NB. MAPX -: strmapc CMAP NB. 1 NB. NB. AUTHOR NB. (C) Oleg Kobchenko , 10/12/2003 NB. GPL, AS-IS, NO WARRANTY NB. NB. 10/23/2003 added strmap[x|c] coclass 'map' NB.*ndxmap v index of the key NB. INDEX=: 'key' ndxmap MAP ndxmap=: (i. boxopen)~ getmap NB.*hasmap v existance of the key NB. BOOL=: 'key' hasmap MAP hasmap=: ndxmap < #@] NB.*ismap v being a map NB. BOOL=: ismap MAP ismap=: ((2: = {:) *. 2: = #)@$ NB.*getmap v [dyad] value for a key NB. VALUE=: 'key' getmap MAP NB.*getmap v [monad] list map keys NB. KEYS=: geymap MAP getmap=: ({."1) : ((,&1@ndxmap {:: ]) :: empty) NB.*setmap a [dyad] add/change map value NB. MAP=: VALUE 'key' setmap MAP NB.*setmap a [monad] remove map entry NB. MAP=: 'key' setmap MAP setmap=: 1 : 0 if. (#y.) <: i=. u. ndxmap y. do. y. return. end. (0 i } (#y.)#1) # y. : if. (#y.) <: i=. u. ndxmap y. do. y.,(boxopen u.), )@.(*@#@]) getmapx i getmap y. end. end. : for_i. <;._2 (>x.),DELIM do. y.=. i getmap y. end. ) NB.*setmapx a [dyad] add/change value for a deep nexted key NB. MAPX=: VALUE 'k1.k2.k3' setmapx MAPX NB.*setmapx a [monad] remove a nested entry NB. MAPX=: 'k1.k2.k3' setmapx MAPX setmapx=: 1 : 0 (empty'') u. setmapx y. : E=. x. -: empty'' r=. ,< y=. y. for_i. }:KEYS=. <;._2 (>u.),DELIM do. y=. i getmap y if. (#*.-.@ismap) y do. if. E do. y. return. end. y=. ,:'';y end. r=. r, {:r else. q=. x. end. for_i. |.i.(#KEYS)-E do. q=. q (i{KEYS) setmap >i{r end. ) NB.*flatmap v convert nested map to flat map of leaves NB. MAP=: flatmap MAPX flatmap=: ([ ,. (getmapx&.> <))~ getmapx NB.*flatmapx v convert flat map to nested NB. MAPX=: flatmapx MAP flatmapx=: 3 : 0 r=. empty'' for_i. y. do. 'k v'=. i r=. v k setmapx r end. ) linear=: 3 : '5!:5<''y.''' box2str=: ;@:(,&LF&.>)@(<"1@:>@{. <@(, ' '&,)&>"0 (linear&.>)@{: )@|: str2box=: (i.&' ' ({. ; ".@}.) ]);._2 NB.*strmap v convert nested map to multiline string NB. STR=: strmap MAPX strmap=: box2str @: flatmap NB.*strmapx v convert multiline string to nested map NB. MAPX=: strmapx STR strmapx=: flatmapx @: str2box stemtails=: ;@:(<@(i.&' ' {. ]) (<@, ,&LF)&>"0 ' .'&(E. <;._1 ])) NB.*strmapc v convert compact string to nested map NB. MAPX=: strmapc CSTR NB. NB. Compact string representation of a nested map is an extension NB. of multiline string (strmap), except it allows multiple keys per line. NB. NB. Each line of compact string consists of NB. stem .tail1 value1 .tail2 value2 ... NB. stem: first non-space chars, NB. forms beggining of the key NB. tailI: non-space chars preceded with ' .' NB. forms end of key NB. valueI: value of the key NB. NB. Both stem and tails may contain multiple parts of the key, NB. separated with '.', but it's important that tails always NB. begin with a '.' strmapc=: [: strmapx [: ; <@stemtails;._2