如何将项目列表Map到Erlang记录

3zwjbxry  于 2022-12-08  发布在  Erlang
关注(0)|答案(3)|浏览(133)

二郎初来乍到!
我有一个元素列表,我想将其中的一些元素Map到具有记录的项。

List = ["a", "b", "c", "d", "e"].

我还有一条记录定义如下:

-record(a_record, { itemA = "", itemB = ""}).

我想将列表Map到与记录定义匹配的元组中,这样我就得到了:

#a_record{itemA="A", itemB="B" }.

我正在查看列表模块,但还看不到一个干净的解决方案。
谢谢你的帮助!

cpjpxq1n

cpjpxq1n1#

如果您可以保证列表中的元素与要初始化的记录字段的顺序相同,并且列表中的元素数至少与记录中的字段数相同,那么您可以利用记录是隐藏在表中的元组这一事实,通过一些技巧从列表中创建记录的示例。例如,您的a_record表示为一个元组,其第一个元素是原子a_record,后跟2个元素,每个元素对应一个记录字段。

1> List = ["a", "b", "c", "d", "e"].
["a","b","c","d","e"]
2> rd(a_record, { itemA = "", itemB = ""}).
a_record
3> ARecord = list_to_tuple([a_record|lists:sublist(List,size(#a_record{})-1)]).
#a_record{itemA = "a",itemB = "b"}

命令1定义了我们的List,在命令2中,我们使用shell命令rd定义了一个记录,就像您的问题中的记录一样。命令3构建了一个新的列表,该列表由记录名作为头部,字段初始化器作为尾部组成。size/1函数为我们提供了记录中的字段数(包括其名称)。因此我们将其减去1,并将得到的值作为List的子列表的大小,用于初始化记录字段。然后,我们将得到的列表传递给list_to_tuple/1,正如您所看到的,结果是一个用List中的值初始化的a_record示例。

1yjd4xko

1yjd4xko2#

您可以使用record_info/2和list_to_tuple/1:

List = ["a", "b", "c", "d", "e"],
   List2 = [string:to_upper(P) || P <- lists:sublist(List, record_info(size, a_record)-1)],
   list_to_tuple([a_record | List2]).
rggaifut

rggaifut3#

我认为更安全的做法是执行列表解析,并从Map中检索与记录中的字段相关联的键。您可能会得到一个充满未定义字段的记录,但您不需要做任何检查来确保Map与记录具有相同数量的键/值,也不需要关心任何顺序。

RecordType = a_record.
RecordFields = record_info(fields, a_record).
Map = #{a_record_field => <<"a record value">>}.
Record = map_to_record(Map, RecordType, RecordFields).
 
map_to_record(Map, RecordType, RecordFields) ->
  RecordValues = [maps:get(RecordField, Map, undefined) || RecordField <- RecordFields],
  AlmostRecord = [RecordType | RecordValues],
  list_to_tuple(AlmostRecord).

如果Map键是二进制字符串,那么需要将记录字段列表中的原子转换为二进制字符串。
值得注意的是,record_info(fields, RecordType)不是对record_info函数的有效调用。我认为这是因为record_info的返回值是在编译时确定的,因为记录本身基本上是类型化元组的语法糖性质,运行时调用是无效的。

相关问题