orddict 是用List实现的有序Dictionary. orddict按照Key进行排序,Key值不重复(对比一下proplists).每一次增加新数据项都会进行重新排序,所以通常情况查找会非常快.由于也是List和tuple实现,所以和proplists一样orddict也不适合大数据量的情况.注意orddict进行Key比较使用的是相等(==).通过模块暴露出来的接口完成对orddict的处理,不要当作普通的list直接处理,因为一些操作会涉及到重排序.
 
  
   
  LYSE上提到orddict在复杂性和效率上达到折中,元素最好不要超过75个.
 
  Orddicts are a generally good compromise between complexity and efficiency up to about 75 elements (see my benchmark). After that amount, you should switch to different key-value stores.
 
  由于orddict实际上就是一个List的实现,相比proplists它的实现要简单很多.大多数方法都是下面逻辑的微调:
 
store(Key, New, [{K,_}=E|Dict]) when Key < K ->
    [{Key,New},E|Dict];
store(Key, New, [{K,_}=E|Dict]) when Key > K ->
    [E|store(Key, New, Dict)];
store(Key, New, [{_K,_Old}|Dict]) ->          %Key == K
    [{Key,New}|Dict];         
store(Key, New, []) -> [{Key,New}].

比如:

append(Key, New, [{K,_}=E|Dict]) when Key < K ->
    [{Key,[New]},E|Dict];
append(Key, New, [{K,_}=E|Dict]) when Key > K ->
    [E|append(Key, New, Dict)];
append(Key, New, [{_K,Old}|Dict]) ->          %Key == K
    [{Key,Old ++ [New]}|Dict];
append(Key, New, []) -> [{Key,[New]}].
再比如:
append_list(Key, NewList, [{K,_}=E|Dict]) when Key < K ->
    [{Key,NewList},E|Dict];
append_list(Key, NewList, [{K,_}=E|Dict]) when Key > K ->
    [E|append_list(Key, NewList, Dict)];
append_list(Key, NewList, [{_K,Old}|Dict]) ->          %Key == K
    [{Key,Old ++ NewList}|Dict];
append_list(Key, NewList, []) ->
    [{Key,NewList}].

 

Practice 

Eshell V5.9.1  (abort with ^G)
1>  D0 = orddict:new().
[]
2>  D1 = orddict:store(files, [], D0),
  D2 = orddict:append(files, f1, D1),
  D3 = orddict:append(files, f2, D2),
  D4 = orddict:append(files, f3, D3),
  orddict:fetch(files, D4).
[f1,f2,f3]
3> b().
D0 = []
D1 = [{files,[]}]
D2 = [{files,[f1]}]
D3 = [{files,[f1,f2]}]
D4 = [{files,[f1,f2,f3]}]
ok
4>   D5 = orddict:append(dirs, dd, D4),
D5.
[{dirs,[dd]},{files,[f1,f2,f3]}]
5>   D6 = orddict:append(a, abc, D5).
[{a,[abc]},{dirs,[dd]},{files,[f1,f2,f3]}]
6>   D7 = orddict:append(z, abc, D6).
[{a,[abc]},{dirs,[dd]},{files,[f1,f2,f3]},{z,[abc]}]
7> orddict:fetch_keys(D7).
[a,dirs,files,z]
8> orddict:fetch(a,D7).
[abc]
9> orddict:fetch(files,D7).
[f1,f2,f3]

 
 
 

10> D7.
[{a,[abc]},{dirs,[dd]},{files,[f1,f2,f3]},{z,[abc]}]
11> orddict:append(z, qqq, D7).
[{a,[abc]},{dirs,[dd]},{files,[f1,f2,f3]},{z,[abc,qqq]}]
12> orddict:store(z, qqq, D7).
[{a,[abc]},{dirs,[dd]},{files,[f1,f2,f3]},{z,qqq}]
13>
 
 
 orddict:store
17> D7.
[{a,[abc]},{dirs,[dd]},{files,[f1,f2,f3]},{z,[abc]}]
18> orddict:store(k,lala, D7).
[{a,[abc]},
{dirs,[dd]},
{files,[f1,f2,f3]},
{k,lala},
{z,[abc]}]
20> orddict:append_list(k, [qqq], v(18)).
** exception error: bad argument
     in operator  ++/2
        called as lala ++ [qqq]
     in call from orddict:append_list/3
     in call from orddict:append_list/3
21> orddict:append_list(k, qqq, v(18)).
** exception error: bad argument
     in operator  ++/2
        called as lala ++ qqq
     in call from orddict:append_list/3
     in call from orddict:append_list/3
22>
 
 orddict:erase
22> D7.
[{a,[abc]},{dirs,[dd]},{files,[f1,f2,f3]},{z,[abc]}]
23> orddict:erase(a,D7).
[{dirs,[dd]},{files,[f1,f2,f3]},{z,[abc]}]
24>
 
 
orddict:filter
filter(Pred, Orddict1) -> Orddict2
Pred = fun(Key, Value) -> bool()
 
28> orddict:filter(fun(K,N)->is_list(N) andalso length(N) >1 end ,D7).
[{files,[f1,f2,f3]}]
29>
 
 
orddict:fold
fold(Fun, Acc0, Orddict) -> Acc1
Fun = fun(Key, Value, AccIn) -> AccOut
29> orddict:fold(fun(K,V,N)-> length(V)+N end ,0,D7).
6
30>
 
orddict:from_list
from_list(List) -> Orddict
List = [{Key, Value}]
注意:重复数据项出现的时候,会采用最后出现的Value值
30> orddict:from_list([{a,1},{b,2},{c,3}]).
[{a,1},{b,2},{c,3}]
31> orddict:from_list([{z,1},{b,2},{c,3}]).
[{b,2},{c,3},{z,1}]
32> orddict:from_list([{"zen",1},{b,2},{c,3}]).
[{b,2},{c,3},{"zen",1}]
33> orddict:from_list([{"zen",1},{b,2},{c,3},{1.0,p},{1,q}]).
[{1,q},{b,2},{c,3},{"zen",1}]
34>
 
orddict:is_key
34> orddict:is_key(z,D7).
true
35> orddict:is_key(p,D7).
false
36>
 
orddict:map
map(Fun, Orddict1) -> Orddict2
Fun = fun(Key, Value1) -> Value2
 
36> orddict:map(fun(K,V)->{K,{K,V,term_to_binary(V)}} end ,D7).
[{a,{a,{a,[abc],<<131,108,0,0,0,1,100,0,3,97,98,99,106>>}}},
{dirs,{dirs,{dirs,[dd],
                   <<131,108,0,0,0,1,100,0,2,100,100,106>>}}},
{files,{files,{files,[f1,f2,f3],
                      <<131,108,0,0,0,3,100,0,2,102,49,100,0,2,102,50,100,0,
                        2,...>>}}},
{z,{z,{z,[abc],<<131,108,0,0,0,1,100,0,3,97,98,99,106>>}}}]
37>
 
 orddict:update
38> orddict:update(a,fun(V)-> term_to_binary(V) end,D7).
[{a,<<131,108,0,0,0,1,100,0,3,97,98,99,106>>},
{dirs,[dd]},
{files,[f1,f2,f3]},
{z,[abc]}]
39> orddict:update(dvd,fun(V)-> term_to_binary(V) end,D7).
** exception error: no function clause matching
                    orddict:update(dvd,#Fun<erl_eval.6.13229925>,
                                   [{files,[f1,f2,f3]},{z,[abc]}])
     in function  orddict:update/3
40> orddict:update(dvd,fun(V)-> term_to_binary(V) end,not_found,D7).
[{a,[abc]},
{dirs,[dd]},
{dvd,not_found},
{files,[f1,f2,f3]},
{z,[abc]}]
41>
 
 
orddict:update_counter
update_counter(Key, Incr, D) ->
    update(Key, fun (Old) -> Old + Incr end, Incr, D).
 
47> orddict:update_counter(a,1,[{a,10},{b,13},{c,16}]).
[{a,11},{b,13},{c,16}]
48>

 

 晚安!