bson-erlang
module变成了BSON编码的JSON,如下所示:
{ "salutation" : "hello",
"subject" : "world" }
进入像这样的Erlang元组:
{ salutation, <<"hello">>, subject, <<"world">> }
现在,我正在尝试与之交谈的服务器可以按任意顺序放置这些字段,并且可能还有其他字段,我不关心,所以 - 同样有效 - 我可能会看到这个:
{ subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> }
有没有什么方法可以指定一个函数模式来提取元组的特定部分,基于它之前出现的元组?
如果我尝试以下操作,它会因“没有函数子句匹配...”而失败,因为元组的arity是错误的,并且因为我关心的字段不在正确的位置:
handle({ salutation, Salutation, _, _ }) -> ok.
这可能吗?有更好的方法吗?
答案 0 :(得分: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
答案 1 :(得分: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
的优势尚不清楚。