2013-10-09 45 views
1

bson-erlang module变成BSON编码的JSON像这样的:模式匹配上BSON元组

{ "salutation" : "hello", 
    "subject" : "world" } 

到二郎元组是这样的:

{ salutation, <<"hello">>, subject, <<"world">> } 

现在,服务器我试图说话可以把这些字段以任何顺序排列,并且可能有额外的字段在那里,我不在乎,所以 - 同样有效 - 我可能会看到这个:

{ subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> } 

有没有什么办法可以指定一个函数模式,根据紧挨着它出现的那个提取特定的元组块?

如果我尝试以下时,出现“无功能的语句匹配......”因为元组的元数是错误的,因为我关心的领域是不是在正确的位置:

handle({ salutation, Salutation, _, _ }) -> ok. 

这可能吗?有一个更好的方法吗?

回答

0
T = { subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> }, 
L = size(T), 
L1 = [{element(I,T),element(I+1,T)} || I <- lists:seq(1,L,2)]. 

[{subject,<<"world">>}, 
{salutation,<<"hello">>}, 
{reason,<<"nice day">>}] 

proplists:get_value(salutation,L1).       
<<"hello">> 

,如果你想在所有1:

F = fun(Key,Tup) -> proplists:get_value(Key,[{element(I,Tup),element(I+1,Tup)} || I <- lists:seq(1,size(Tup),2)]) end. 

F(reason,T). 
<<"nice day">> 
F(foo,T). 
undefined 
+0

我已经可以用'bson:at'做到了,尽管这很有用,谢谢。我想知道我是否可以用模式做到这一点? –

+0

我认为如果你事先不知道它的长度,并且不想将它转换成其他类型的列表,就不可能匹配tupple的内部元素。 – Pascal

0

没有模式的一个未知长度的前缀之后,匹配成功从一个可变长度的结构值。元组,列表和二进制文件都是如此。事实上,这种模式将需要通过结构递归。

列表的常用方法是通过分割头部和尾部来进行递归,这是典型的函数式语言。

f_list([salutation, Salutation | _]) -> {value, Salutation}; 
f_list([_Key, _Value | Tail]) -> f_list(Tail); 
f_list([]) -> false. 

请注意,如果列表包含奇数个元素,则此函数可能失败。

对于元组也可以使用相同的方法,但是需要guards而不是匹配模式,因为没有模式可以提取元组尾部的等价物。事实上,元组不是链接列表,而是具有O(1)访问其元素(及其大小)的结构。

f_tuple(Tuple) -> f_tuple0(Tuple, 1). 

f_tuple0(Tuple, N) when element(N, Tuple) =:= salutation -> 
    {value, element(N + 1, Tuple)}; 
f_tuple0(Tuple, N) when tuple_size(Tuple) > N -> f_tuple0(Tuple, N + 2); 
f_tuple0(_Tuple, _N) -> false. 

同样,如果元组包含奇数个元素,则此函数可能失败。

基于问题中的元素,虽然守护者优于bson:at/2的优势尚不明确。