The Proplists module is suitable for scenarios with less data, and is often used for processing configuration files and function options. proplists The internal data structure is the Key-value key-value pair form, the first element does the key to query and delete, if a key has more than one value will use the first occurrence of the value, Others are ignored. Proplists is extremely loose on key and value, and can be any term (). You can even make the {atom,true} abbreviation Atom. It is also because of such loose data constraints that the Proplists module does not have the means to update and append data items , you need to use Lists:replace/4.key to compare the =:= exact equals, which will determine the type and value.
5> Proplists:get_value (1,[{1,a},{1.0,b},{1,c}]) .a6> proplists:append_values (1,[{1,a},{1.0,b},{1,c}]). [a,c]8>
Specification and compression mentioned in the form of atom abbreviation, Atom form becomes the compression format, {atom,true} form becomes canonical form. This is the property of two forms, which is defined as-type property ():: Atom () | Tuple (). There is a property method in the module that specializes in data normalization.
Property ({key, true})-property, Key;property, Is_atom (key) . The form of the call:16> Proplists:property ({a}). {a}17> proplists:property ({a,true}). A
Compression is actually a one-to-one element within the proplists execution PROPERTY/1, namely: [Property (P) | | P <-List].
10> Proplists:compact ([{A, true}, {B, true}, {A, 3}, {C, true}, {A, [4]}]). [ A,B,{A,3},C,{A,[4]}]
Functions that are expanded if the calculation has compression
Unfold ([P | PS]), if Is_atom (p) , [{p, true} | unfold (PS)]; True, [P | unfold (Ps)] end;unfold ([]), [].12> proplists:unfold ([Foo,bar,test,haha]). [ {foo,true},{bar,true},{test,true},{haha,true}]13> Proplists:unfold ([Foo,bar,{test,false},haha]). [ {foo,true},{bar,true},{test,false},{haha,true}]14> proplists:unfold ([foo, "Zen", Bar,{test,false},haha]). [ {foo,true}, "Zen",{bar,true},{test,false},{haha,true}]15> proplists:unfold ([foo, "Zen", 23,{test,false}, Haha]). [{foo,true}, "Zen", 23,{test,false},{haha,true}]
Proplists related operations take a look at the general operation of Proplists, there are some ways to pay attention to the details.
append_values(Note that less spelling of a s) combines all key values with the same data item, and value is integrated in the list.
1> Proplists:append_values (A, [{A, []}, {b, 0}, {A, 3}, {C,-1}, {A, [4]}]). [1,2,3,4]2> Proplists:append_values (A, [{A, b}, {b, 0}, {A, 3}, {C,-1}, {A, [4]}]). [b,3,4]3> Proplists:append_values (A, [{A, b}, {b, 0}, {A, 3}, {C,-1}, {A, [[4]]}]). [b,3,[4]]1> Proplists:append_values (A, [{A, [up]}, {"Zen", 0}, {A, 3}, {C,-1}, {A, [4]}]). [1,2,3,4]2> Proplists:append_values (A, [{A, [1,2]},b]). [1,2]3> Proplists:append_values (b, [{A, [1,2]},b]). [true]4>
Deletemethod deletes all data items that are equal to the key value:
Percent Delete (Key, List), list18> Proplists:delete (A, [{A, true}, {B, true}, {A, 3}, {C, true}, {A, [4]}]). [ {B,true},{c,true}]
CompactCompress the data
10> Proplists:compact ([{A, true}, {B, true}, {A, 3}, {C, true}, {A, [4]}]). [ A,B,{A,3},C,{A,[4]}]
get_all_values gets all data items that are equal to the key value:
8> Proplists:get_all_values (A, [{A, [up]}, {"Zen", 0}, {A, 3}, {C,-1}, {A, [4]}]). [[1,2],3,[4]]9>
Get_boolThis method is still a bit of a trap, its intention is to see the key value when the first occurrence of the value is True|false.
Get_bool (Key, [P | Ps]), if Is_atom (p), p =:= Key, true; Tuple_size (P) >= 1, Element (1, P) =:= Key--Case P of {_, true}-& Gt True _-A-percent Don ' t continue the search! False end; True-Get_bool (Key, Ps) End;get_bool (_key, []), False.9> Proplists:get_bool (A, [{A, [up]} {"Zen", 0}, {A, 3}, {C,-1}, {A, [4]}]) .false10> Proplists:get_bool (A, [{A,]}, {"Zen", 0}, {A, 3},a, {C,-1}, {a , [4]}]) .false11> Proplists:get_bool (A, [A,{a, [up]}, {"Zen", 0}, {A, 3},a, {C,-1}, {A, [4]}]) .true12> proplists:g Et_bool (A, [{A,true},{a, []}, {"Zen", 0}, {A, 3},a, {C,-1}, {A, [4]}]) .true13> Proplists:get_bool (A, [{a,false},{a, [Up]}, {"Zen", 0}, {A, 3},a, {c, -1},{a, [4]}]) .false14> proplists:get_bool (q, [{A,truE},{a, [up]}, {"Zen", 0}, {A, 3},a, {C,-1}, {A, [4]}]) .false15> proplists:get_bool (q, ["abc", {A,true},{a, []}, {"Z En ", 0}, {A, 3},a, {c,-1}, {A, [4]}]) .false16> Proplists:get_bool (" abc ", [" abc ", {a,true},{a, [+]}, {" Zen ", 0}, {A, 3} , A,{c,-1}, {A, [4]}]) .false17> Proplists:get_bool ("abc", [{"ABC", True},{a,true},{a, [up]}, {"Zen", 0}, {a,3},a, {C, -1}, {A, [4]}]). True
Get_keysGet all the keys that are not duplicated
18> Proplists:get_keys ([{"ABC", True},{a,true},{a, [up]}, {"Zen", 0}, {A, 3},a,{c,-1}, {A, [4]}]). ["Zen", A,c, "abc"]19> Proplists:get_keys ([{a,true},{a,true},{a, [+]}, {"Zen", 0}, {A, 3},a, {c,-1}, {A, [4]}]). ["Zen", A,c]
Get_valueBy key, the first occurrence of value is obtained
get_value (Key, [P | Ps], Default), if Is_atom (p), p =:= Key, true; Tuple_size (P) >= 1, Element (1, P) =:= Key, Case P of {_, Value}, Value; _--Don</code>t continue the search! Default end; True-Get_value (Key, Ps, default) End;get_value (_key, [], default), Default.3> Proplists:get_va Lue ([A, b], ["Packet", [A, b], "Login", 22,2,s,f], "none"). " None "4> proplists:get_value (" Login ", [" Packet ", [A, b]," Login ", 22,2,s,f]," none "). None "5> proplists:get_value (login, [" Packet ", [A, b]," Login ", 22,2,s,f]," none "). "None" 1> proplists:get_value ([A, b], ["Packet", {[A,b],bingo}, "Login", 22,2,s,f], "none") .bingo2> Proplists:get _value (S, ["packet", {[A,b],bingo}, "Login", 22,2,s,f], "none"). True3>
look_upUnlike Get_value, the return is {Key,value}
Lookup_all
8> Proplists:lookup_all (A, [{a,1},{a, b}, {b, 0}, {A, 3}, {C,-1}, {A, [[4]]}]). [{a,1},{a,b},{a,3},{a,[[4]}]
is_definedWhether a specific key value exists
6> proplists:is_defined (S, ["packet", {S,kill},{[a,b],bingo}, "Login", 22,2,s,f]) .true7> proplists: Is_defined (P, ["Packet", {S,kill},{[a,b],bingo}, "Login", 22,2,s,f]) .false8>
Splitgrouping data by key value
9> Proplists:split ([{C, 2}, {e, 1}, A, {C, 3, 4}, D, {B, 5}, b], [A, B, C]). {[[a],[{b,5},b],[{c,2},{c,3,4}]],[{e,1},d]}10> Proplists:split ([{C, 2}, {c,23},{a,false},{e, 1}, A, {C, 3, 4}, D, {b, 5}, b], [A, B, C]). {[[{a,false},a],[{b,5},b],[{c,2},{c,23},{c,3,4}]],[{e,1},d]}11>
A group of the following several methods we put together to see
ExpandDo is to replace the key in the list with the corresponding value, note that this method expands the object is the property
substitute_aliasesReplace the corresponding key value with an alias
1> proplists:substitute_aliases ([{zen, "Ligaoren"},{0,zero}],[zen,{zen,zen},{abc,zen},{zen,tick},0,{0,1},{ 23,0}]). [{"Ligaoren", true},{"Ligaoren", zen},{abc,zen},{"Ligaoren",tick},0,{zero,1},{23,0}]2>
substitute_negationsKey value substitution, value reverse
2> proplists:substitute_negations ([{zen, "Ligaoren"},{0,zero}],[zen,{zen,zen},{abc,zen},{zen,tick},0,{0,1},{ 23,0}]). [{"Ligaoren", false},{"Ligaoren", true},{abc,zen},{"Ligaoren",true},0,zero,{23,0}]3> Proplists:substitute_ Negations ([{zen, "Ligaoren"},{0,zero}],[zen,{zen,zen},{abc,zen},{zen,tick},0,{0,true},{23,0}]). [{"Ligaoren", false},{"Ligaoren", true},{abc,zen},{"Ligaoren",true},0,{zero,false},{23,0}]4> proplists: Substitute_negations ([{zen, "Ligaoren"},{0,zero}],[zen,{zen,zen},{abc,zen},{zen,tick},0,{0,false},{23,0}]). [{"Ligaoren", false},{"Ligaoren", true},{abc,zen},{"Ligaoren", true},0,zero,{23,0}]
NormalizeIntegrated with substitute_aliases Substitute_negations expand
2> proplists:normalize ([A,b,c,d,e,f,g],[{aliases, [{b,b2},{e,email}]}]). [a,b2,c,d,email,f,g]3> proplists:normalize ([A,b,c,d,e,f,g],[{aliases, [{b,b2},{e,email}]}]). [a,b2,c,d,email,f,g]4> proplists:normalize ([A,b,c,d,e,f,g],[{aliases, [{negations, [a,f]}]}]). [a,b,c,d,e,f,g]5> proplists:normalize ([a,b,c,d,e,f,g],[{expand, [{d,do_it_by_yourself},{g,1000}]}]). [a,b,c,do_it_by_yourself,e,f,1000]
Application examples
6> test:module_info (Compile).
Mochiweb item parsing the header cookie uses proplist in multiple places:
Parse_form_outer (EOF, _, ACC), lists:reverse (ACC);p Arse_form_outer ({headers, H}, Filehandler, state), {"Form-data", H1} = Proplists:get_value ("Content-disposition", H), Name = Proplists:get_value ("name", H1), filename = proplists:get_value ("filename", H1), case filename of Undefined (next), Parse_form_value (Next, {Name, []}, Filehandler, state) end; _- ContentType = Proplists:get_value ("Content-type", H), Handler = Filehandler (Filename, ContentType), Fun (Next)- Parse_form_file (Next, {Name, Handler}, Filehandler, state) end end.
One example of parsing options:
%%% 18> proplists:lookup (Loop,[{ip, "127.0.0.1"},{loop, {mochiweb_http, default_body}}]).%%% {Loop,{mochiweb _http,default_body}}parse_options (options), {loop, httploop} = Proplists:lookup (loop, options), loop = Fun (S) ? Module:loop (S, Httploop) end, Options1 = [{loop, loop} | Proplists:delete (Loop, Options)], Mochilists:set _defaults (? DEFAULTS, Options1).
Last: Estimate 90% of the cases we only use Proplists:get_value:)
2012-8-22 Update
Proplists:get_value performance is much worse than Lists:keyfind,
Lists the following methods are BIF implementation: Percent BIFS:KEYMEMBER/3, KEYSEARCH/3, KEYFIND/3
And Proplists:get_value is Erlang implementation, I think this is the root cause of performance differences;
Here is a discussion that is basically the same judgment: http://www.ostinelli.net/erlang-listskeyfind-or-proplistsget_value/
-module (PVSL).-define (list_sizes, [10000, 100000, 1000000]).-define (retries).-compile (Export_all). Start ()- >% test for different list sizes Lists:foreach (fun (n), Test_list (n) end,? list_sizes). Test_list (listsize),% generate a list of size listsize of {Key, Val} entries keylist = [{K , K} | | K <-lists:seq (1, listsize)],% test this list against both functions Lists:foreach (Fun (Type), get_v Al (Type, Now (), Keylist, Listsize,? Retries) end, [proplists, lists]).% test getting values, compute necessary time and output print Resultsget _val (Type, start, _keylist, Listsize, 0), T = Timer:now_diff (now (), start), Io:format ("Computed ~p Rand Om key searches on a ~p-sized list in ~p ms using ~p~n ", [? Retries, Listsize, t/1000, Type]), Get_val (Proplists, Start, Keylist, Listsize, Tries), Proplists:get_value (ran Dom:uniform (listsize), keylist), Get_val (Proplists, StaRT, Keylist, Listsize, Tries-1), Get_val (lists, Start, Keylist, Listsize, Tries), Lists:keyfind (random:unifor M (listsize), 1, keylist), Get_val (lists, Start, Keylist, Listsize, Tries-1). I ran this test on my MacBook Pro, the Intel Core i5 2.4GHz with 4GB Memory, and the Erlang r13b04, with Kernel Polling enabled. These is the results.roberto$ Erl +k true +p 1000000Erlang r13b04 (erts-5.7.5) [source] [Smp:4:4] [rq:4] [async-threads:0 ] [HiPe] [Kernel-poll:true]eshell V5.7.5 (abort with ^g) 1> C (PVSL). {ok,pvsl}2> Pvsl:start (). computed-random key searches on a 10000-sized list in 323.373 ms using proplistscomputed $ random key searches on a 10000-sized list in 12.897 ms using listscomputed-random key searches on a 100000-sized List in 3273.973 ms using proplistscomputed-random key searches on a 100000-sized list in 130.592 ms using Listscomp uted random key searches on a 1000000-sized list in 34131.905 ms using proplistscomputed-random key SeaRches on a 1000000-sized list in 2050.627 ms using listsok3>
Erlang--proplists Structure Analysis