[英]ETS table - Updating maps as records
示例代码:
defmodule Foo do
def fast_cars_cache do
fast_cars =
{
%{color: "Red", make: "Mclaren", mileage: 15641.469},
%{color: "Blue", make: "Ferrari", mileage: 120012.481},
%{color: "Red", make: "Ferrari", mileage: 29831.021},
%{color: "Black", make: "Ferrari", mileage: 24030.674},
%{color: "Cobalt", make: "Ferrari", mileage: 412.811},
%{color: "Blue", make: "Koenigsegg", mileage: 250.762},
%{color: "Cobalt", make: "Koenigsegg", mileage: 1297.76},
%{color: "Titanium", make: "Koenigsegg", mileage: 5360.336},
%{color: "Blue", make: "Maserati", mileage: 255.78}
}
if Enum.member?(:ets.all(), :fast_cars_cache) do
:ets.delete(:fast_cars_cache)
:ets.new(:fast_cars_cache, [:duplicate_bag, :public, :named_table])
:ets.insert(:fast_cars_cache, fast_cars)
else
:ets.new(:fast_cars_cache, [:duplicate_bag, :public, :named_table])
:ets.insert(:fast_cars_cache, fast_cars)
end
end
def update_record do
fast_cars_cache()
old_record = :ets.first(:fast_cars_cache)
new_record =
%{color: "Black", make: old_record.make, mileage: 1641.469}
:ets.delete(:fast_cars_cache, {old_record})
|> IO.inspect(label: "Old record deleted")
:ets.insert(:fast_cars_cache, {new_record})
:ets.tab2list(:fast_cars_cache)
end
end
Output:
iex(1)> Foo.update_record
Old record deleted: true
[
{%{color: "Red", make: "Mclaren", mileage: 15641.469},
%{color: "Blue", make: "Ferrari", mileage: 120012.481},
%{color: "Red", make: "Ferrari", mileage: 29831.021},
%{color: "Black", make: "Ferrari", mileage: 24030.674},
%{color: "Cobalt", make: "Ferrari", mileage: 412.811},
%{color: "Blue", make: "Koenigsegg", mileage: 250.762},
%{color: "Cobalt", make: "Koenigsegg", mileage: 1297.76},
%{color: "Titanium", make: "Koenigsegg", mileage: 5360.336},
%{color: "Blue", make: "Maserati", mileage: 255.78}},
{%{color: "Black", make: "Mclaren", mileage: 1641.469}}
]
观察/问题:
IO.inspect
, old_record
已被删除,正如tab2list
显示的那样,该记录仍然存在。 这是为什么?old_record
从未被删除,那么代码需要进行哪些调整才能完成此操作?:ets.select_replace
(如果适用)一步执行此更新,但我无法对匹配规范要求做出正面或反面的规定。 如果有人可以根据上面的示例用一两个示例来消除歧义,那将非常有帮助。一如既往,非常感谢您的有用指导和建议:)
您应该清楚地区分映射和元组。 Map
是一个键值结构。 Tuple
不是。
:ets
记录是元组,而不是映射。
您的初始结构是地图元组。 一个元组,有许多地图。 它作为单个元素插入到:ets
中,这在您的 output 中清晰可见(检查花括号。)
我猜你要在缓存中插入许多元素。
iex|1 ▶ :ets.new(:fast_cars_cache, [:duplicate_bag, :public, :named_table])
iex|2 ▶ fast_cars = [
...|2 ▶ {"Red", "Mclaren", 15641.469},
...|2 ▶ {"Blue", "Ferrari", 120012.481},
...|2 ▶ {"Red", "Ferrari", 29831.021}
...|2 ▶ ]
iex|3 ▶ :ets.insert(:fast_cars_cache, fast_cars)
:ets.first/1
,如文档中所述,返回第一个 key 。 :ets.detele/2
按键删除一条记录,并且您的代码将从:ets.first/1
返回的任何内容包装到一个单元素元组中,使:ets.delete/2
都是无操作的(是的, :ets.delete/2
总是返回true
。)
iex|4 ▶ :ets.first(:fast_cars_cache)
#⇒ "Red"
iex|5 ▶ :ets.delete(:fast_cars_cache, {"Red"}) # NOOP
#⇒ true
iex|6 ▶ :ets.delete(:fast_cars_cache, "Red") # DELETED
#⇒ true
然后如果你想插入一条新记录,创建一个元组并插入它,不要创建一个包装成单元素元组的 map。 要按键获取旧记录,通常使用:ets.lookup/2
或更复杂的:ets.select
。
iex|7 ▶ [{_, make, _}|_] = :ets.lookup(:fast_cars_cache, "Red")
iex|8 ▶ new_record = {"Black", make, 1641.469}
iex|9 ▶ :ets.insert(:fast_cars_cache, new_record)
我已经链接了足够的文档以使用:ets.select_replace/2
作为家庭作业。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.