2013-10-09 78 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的優勢尚不明確。