############################################################################ # # Name: lmap.icn # # Title: Map list elements # # Author: Ralph E. Griswold # # Date: June 10, 1988 # ############################################################################ # # The procedure lmap(L1,L2,L3) maps elements of L1 according to L2 # and L3. This procedure is the analog for lists of the built-in # string-mapping function map(s1,s2,s3). Elements in L1 that are # the same as elements in L2 are mapped into the corresponding ele- # ments of L3. For example, given the lists # # L1 := [1,2,3,4] # L2 := [4,3,2,1] # L3 := ["a","b","c","d"] # # then # # lmap(L1,L2,L3) # # produces a new list # # ["d","c","b","a"] # # Lists that are mapped can have any kinds of elements. The # operation # # x === y # # is used to determine if elements x and y are equivalent. # # All cases in lmap are handled as they are in map, except that # no defaults are provided for omitted arguments. As with map, lmap # can be used for transposition as well as substitution. # # Warning: # # If lmap is called with the same lists L2 and L3 as in # the immediately preceding call, the same mapping is performed, # even if the values in L2 and L3 have been changed. This improves # performance, but it may cause unexpected effects. # # This ``caching'' of the mapping table based on L2 and L3 # can be easily removed to avoid this potential problem. # ############################################################################ procedure lmap(L1,L2,L3) static lmem2, lmem3, lmaptbl, tdefault local i, a initial tdefault := [] if type(a := L1 | L2 | L3) ~== "list" then runerr(108,a) if *L2 ~= *L3 then runerr(208,L2) L1 := copy(L1) if not(lmem2 === L2 & lmem3 === L3) then { # if an argument is new, rebuild lmem2 := L2 # save for future reference lmem3 := L3 lmaptbl := table(tdefault) # new mapping table every i := 1 to *L2 do # build the map lmaptbl[L2[i]] := L3[i] } every i := 1 to *L1 do # map the values L1[i] := (tdefault ~=== lmaptbl[L1[i]]) return L1 end