如何在Erlang中将元组对列表转换为记录?

5
假设我有如下代码:
-record(my_record, {foo, bar, baz}).
Keyvalpairs = [{foo, val1}, {bar, val2}, {baz, val3}].
Foorecord = #my_record{foo=val1, bar=val2, baz=val3}.
如何将Keyvalpairs转换为Foorecord呢?
3个回答

18

最简单的做法是:

Foorecord = #my_record{foo=proplists:get_value(foo, Keyvalpairs), 
      bar=proplists:get_value(bar, Keyvalpairs),
      baz=proplists:get_value(baz, Keyvalpairs)}.

如果这样做显得过于重复,您可以进行如下操作:
Foorecord = list_to_tuple([my_record|[proplists:get_value(X, Keyvalpairs)
      || X <- record_info(fields, my_record)]]).

3

就像其他答案所指出的那样,你需要自己编写代码来实现这一点。然而,已经提出的解决方案都是不完整的。例如,它没有考虑记录条目的默认值。我使用以下代码片段来处理此转换:

%% @doc returns a "RECSPEC" that can be used by to_rec in order to 
%% perform conversions
-define(RECSPEC(R), {R, tuple_to_list(#R{}), record_info(fields, R)}).

%% @doc converts a property list into a record.
-spec to_rec(recspec(), proplist()) -> record().
to_rec({R, [_ | N], Spec}, P) when is_atom(R) and is_list(Spec) ->
    list_to_tuple(
      [R | lists:foldl(
         fun ({K,V}, A) ->
             case index_of(K, Spec) of
                 undefined -> 
                     A;
                 I -> 
                     {Head, Tail} = lists:split(I, A),
                      Rest = case Tail of
                                [_ | M] -> M;
                                []      -> []
                            end,
                     Head ++ [V | Rest]
             end
         end, N, P)]).

现在可以简单地做到:
-record(frob, {foo, bar="bar", baz}).

to_rec(?RECSPEC(frob), [{baz, "baz"}, {foo, "foo"}])

这会产生
#frob{foo="foo", bar="bar", baz="baz"}

我把这个放进了我正在构建的一个小型“工具箱”库中,以收集这些小的“片段”,这些片段在开发Erlang应用程序时只是让生活变得更轻松:ETBX

0

如果您的值与记录中的顺序相同,您可以直接将其转换为记录,只需在列表的第一个元素之前加上记录名称,然后将列表转换为元组即可。

Foorecord = list_to_tuple([my_record]++[Val || {_,Val} <- [{foo, val1},{bar, val2},{baz, val3}] ]).

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