traverse_dict
| Definition: | traverse_dict(integer rid, object user_data=0, integer tid=1, bool rev=false) |
| Description: |
Perform an in-order traversal of the dictionary, invoking the specified routine for each {key,data} pairing.
rid: routine_id of a function that accepts three parameters, called for each entry. user_data: any additional data that might be required by rid. tid: a result from new_dict(), or if omitted it uses the one common dictionary. rev: when true, the traversal is made from the highest key to the lowest key. |
| pwa/p2js: | Supported. |
| Comments: |
The specified routine should be a function that accepts three parameters: key, data, and user_data, and
should return 1 to continue the traversal, or 0 to terminate it.
Obviously modifying the key structure of tid during rid is likely to have unintended consequences (updating the data should however be fine). If you are traversing a complex tree structure and rebalance it underfoot, then anything can happen, from skipping whole subtrees, traversing them twice, or a fatal error. However it would be acceptable to terminate and restart the traversal after performing each key update (return 0), that is assuming you can skip any already-done updates on the next traversal. The ordering is case-sensitive. If a case-insensitive ordering is required, the key values as passed to setd() [etc] should be passed through either upper() or lower() and if needs be a copy of the original case included somewhere in data. The use of a named parameter when setting the rev flag is recommended, to make the intent clear and the code easier to read. |
| Example 1: |
function visitor(object key, object data, object /*user_data*/)
?{key,data}
return 1
end function
setd("key","data")
setd("key2","data2")
traverse_dict(routine_id("visitor"))
|
| Example 2: |
constant map1 = new_dict({{"key1","data1"}}),
map2 = new_dict({{"key2","data2"}}),
map3 = new_dict(map1)
function merge(object key, object data, integer map3)
setd(key,data,map3)
return 1
end function
traverse_dict(routine_id("merge"),map3,map2)
include builtins\map.e
?{"map1:",pairs(map1)}
?{"map2:",pairs(map2)}
?{"map3:",pairs(map3)}
-- output
-- {"map1:",{{"key1","data1"}}}
-- {"map2:",{{"key2","data2"}}}
-- {"map3:",{{"key1","data1"},{"key2","data2"}}}
Obviously should the same key occur in map1 and map2, the data from map2 will overwrite the corresponding map1 value. Note that other forms of merge are possible/may be required, for example if key is file size and data is a list of files of that size, the merge operation would probably want to concatenate the values from matching keys rather than replace them, eg:
constant map1 = new_dict({{1234,{"this.txt"}}}),
map2 = new_dict({{1234,{"that.txt"}}}),
map3 = new_dict(map1)
function merge(object key, object data, integer map3)
integer node = getd_index(key,map3)
if node=NULL then
setd(key,data,map3)
-- (possibly return 0 as per comment above)
else
setd(key,getd_by_index(node,map3)&data,map3)
end if
return 1
end function
traverse_dict(routine_id("merge"),map3,map2)
include builtins\map.e
?{"map1:",pairs(map1)}
?{"map2:",pairs(map2)}
?{"map3:",pairs(map3)}
-- output
-- {"map1:",{{1234,{"this.txt"}}}}
-- {"map2:",{{1234,{"that.txt"}}}}
-- {"map3:",{{1234,{"this.txt","that.txt"}}}}
|
| See Also: | setd, upper, lower, routine_id, traverse_dict_partial_key |