将元组转换为属性列表

4

如何将MongoDB中的元组进行转换

{'_id',<<"vasya">>,password,<<"12ghd">>,age,undefined}

转换为属性列表

[{'_id',<<"vasya">>},{password,<<"12ghd">>},{age,undefined}]

看起来应该更改的是mongodb。我也做过这件事,似乎每个人都这样做。所以也许应该由mongodb驱动程序来完成这个任务。 - Eric des Courtis
4个回答

4
假设您想将元组的两个连续元素合并在一起,这并不太难。您可以使用element\2从元组中提取元素,使用tuple_size\1获取元组的大小。以下是处理此操作的几种方式:
1> Tup = {'_id',<<"vasya">>,password,<<"12ghd">>,age,undefined}.
{'_id',<<"vasya">>,password,<<"12ghd">>,age,undefined}
2> Size = tuple_size(Tup).            
6

你可以使用列表推导式来完成这个任务:
3> [{element(X, Tup), element(X+1, Tup)} || X <- lists:seq(1, Size, 2)].
[{'_id',<<"vasya">>},{password,<<"12ghd">>},{age,undefined}]

或者你可以将其压缩:

4> lists:zip([element(X, Tup) || X <- lists:seq(1, Size, 2)], [element(X, Tup) || X <- lists:seq(2, Size, 2)]).
[{'_id',<<"vasya">>},{password,<<"12ghd">>},{age,undefined}]

你可以通过编写一个函数来处理提取元素,从而清理该zip文件。
slice(Tuple, Start, Stop, Step) ->
    [element(N, Tuple) || N <- lists:seq(Start, Stop, Step)].

然后调用这个函数:
5> lists:zip(slice(Tup, 1, Size, 2), Slice(Tup, 2, Size, 2)).
[{'_id',<<"vasya">>},{password,<<"12ghd">>},{age,undefined}]

1

0

或者你可以编写一个简单的函数来完成它:

mongo_to_proplist(MongoTuple) ->
    mongo_to_tuple(MongoTuple, 1, tuple_size(MongoTuple)).

mongo_to_proplist(Mt, I, Size) when I =:= Size -> [];
mongo_to_proplist(Mt, I, Size) ->
    Key = element(I, Mt),
    Val = element(I+1, Mt),
    [{Key,Val}|mongo_to_proplist(Mt, I+2, Size)].

这基本上就是列表推导式版本所做的事情,但展开成了显式循环。


0

虽然不是很高效,所以不要在大型结构上使用它,但确实非常简单:

to_proplist(Tuple) -> to_proplist1(tuple_to_list(Tuple), []).

to_proplist1([], Acc) -> Acc;
to_proplist1([Key, Value | T], Acc) -> to_proplist1(T, [{Key, Value} | Acc]).

如果顺序出现了某些奇怪的问题,可以在 to_proplist1/2 的基本情况下反转 proplist。

1
它不必是尾递归的,因此可以使用to_proplist_([]) -> []; to_proplist_([K, V | T]) -> [{K,V} | to_proplist_(T)].这种递归方式,因为现在这种递归已经足够快了,而且元组已经有了有限的大小。 - Hynek -Pichi- Vychodil
确实,它不必是尾递归的,但通常使用累积参数的尾递归版本会导致记忆使用率波动较小。对于这个特定的函数来说,如果我们有一个足够长的列表需要考虑内存,那么速度会非常慢。 - Jan Henry Nystrom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接