更新列表的值
我有以下设置:
1> rd(rec, {name, value}).
rec
2> L = [#rec{name = a, value = 1}, #rec{name = b, value = 2}, #rec{name = c, value = 3}].
[#rec{name = a,value = 1},
#rec{name = b,value = 2},
#rec{name = c,value = 3}]
3> M = [#rec{name = a, value = 111}, #rec{name = c, value = 333}].
[#rec{name = a,value = 111},#rec{name = c,value = 333}]
列表 L
中的元素根据其 name
是唯一的。我也不知道列表 M
中元素的先前值。我想做的是用列表 M
中的值更新列表 L
,同时保留 L
中不存在的元素M
。我做了以下工作:
update_values([], _M, Acc) ->
Acc;
update_attributes_from_fact([H|T], M, Acc) ->
case [X#rec.value || X <- M, X#rec.name =:= H#rec.name] of
[] ->
update_values(T, M, [H|Acc]);
[NewValue] ->
update_values(T, M, [H#rec{value = NewValue}|Acc])
end.
它完成了这项工作,但我想知道是否有一种使用 bifs 的更简单的方法。
多谢。
I have the following setup:
1> rd(rec, {name, value}).
rec
2> L = [#rec{name = a, value = 1}, #rec{name = b, value = 2}, #rec{name = c, value = 3}].
[#rec{name = a,value = 1},
#rec{name = b,value = 2},
#rec{name = c,value = 3}]
3> M = [#rec{name = a, value = 111}, #rec{name = c, value = 333}].
[#rec{name = a,value = 111},#rec{name = c,value = 333}]
The elements in list L
are unique based on their name
. I also don't know the previous values of the elements in list M
. What I am trying to do is to update list L
with the values in list M
, while keeping the elements of L
that are not present in M
. I did the following:
update_values([], _M, Acc) ->
Acc;
update_attributes_from_fact([H|T], M, Acc) ->
case [X#rec.value || X <- M, X#rec.name =:= H#rec.name] of
[] ->
update_values(T, M, [H|Acc]);
[NewValue] ->
update_values(T, M, [H#rec{value = NewValue}|Acc])
end.
It does the job but I wonder if there is a simpler method that uses bifs.
Thanks a lot.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
没有现有的函数可以为您执行此操作,因为您只想更新值字段而不是替换 L 中的整个记录(如lists:keyreplace() 所做的那样)。如果 L 和 M 都可以很长,我建议如果可以的话,使用 #rec.name 作为键将 L 从列表更改为 dict 或 gb_tree。然后,您可以循环 M,对于 M 中的每个元素,查找正确的条目(如果有)并写回更新的记录。循环可以写成折叠。即使您先将列表 L 转换为字典,然后在循环后再次将其转换回来,它也会比 L*M 方法更有效。但是,如果 M 总是很短,并且您不想在代码的其余部分中将 L 作为字典保留,那么您当前的方法很好。
There's no existing function that does this for you, since you just want to update the value field rather than replacing the entire record in L (like lists:keyreplace() does). If both L and M can be long, I recommend that if you can, you change L from a list to a dict or gb_tree using #rec.name as key. Then you can loop over M, and for each element in M, look up the correct entry if there is one and write back the updated record. The loop can be written as a fold. Even if you convert the list L to a dict first and convert it back again after the loop, it will be more efficient than the L*M approach. But if M is always short and you don't want to keep L as a dict in the rest of the code, your current approach is good.
纯列表理解解决方案:
使用
lists:keyfind/3
更有效:对于大 M 更有效:
但对于真正的大 M,这种方法可能是最快的:
Pure list comprehensions solution:
little bit more effective using
lists:keyfind/3
:even more effective for big M:
but for really big M this approach can be fastest:
您可以使用 lists:ukeymerge/3:
其中:
记录是一个元组,您可以使用#rec.name 以透明的方式返回键的位置。请注意,我恢复了列表 L 和 M,因为该函数保留了第一个列表中的值。
You could use lists:ukeymerge/3:
Which:
A record is a tuple and you can use #rec.name to return the position of the key in a transparent way. Note that I reverted the lists L and M, since the function keeps the value from the first list.