ETS table - 将地图更新为记录
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
输出:
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}}
]
Observations/Questions:
- 根据
IO.inspect
,old_record
被删除了,tab2list
显示,这条记录仍然存在。这是为什么?
- 如果实际上
old_record
从未被删除,代码需要进行哪些调整才能完成此操作?
- 理想情况下,我想利用
:ets.select_replace
(如果适用)一步完成此更新,但我无法确定 stipulations 的正面或反面符合规范要求。如果有人可以根据上面的示例用一两个示例来消除歧义,那将非常有帮助。
一如既往,非常感谢您的指导和建议:)
你应该清楚地区分映射和元组。 Map
is a key-value structure. Tuple
不是。
:ets
记录是元组,不是映射。
您的初始结构是一个映射元组。一个元组,有很多映射。它作为单个元素插入到 :ets
中,这在您的输出中清晰可见(检查大括号。)
我猜你要将许多个元素插入到缓存中。
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
, as it’s stated in the documentation, returns the first key. :ets.detele/2
通过键 删除记录 并且您的代码将从 :ets.first/1
返回的任何内容包装到一个单元素元组中,使 :ets.delete/2
无论如何都是空操作(是的,:ets.delete/2
总是 returns 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
然后如果你想插入一条新记录,创建一个元组并插入它,不要创建一个包裹在单元素元组中的映射。要通过密钥获取旧记录,通常使用 :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
作为作业离开。
示例代码:
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
输出:
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}}
]
Observations/Questions:
- 根据
IO.inspect
,old_record
被删除了,tab2list
显示,这条记录仍然存在。这是为什么? - 如果实际上
old_record
从未被删除,代码需要进行哪些调整才能完成此操作? - 理想情况下,我想利用
:ets.select_replace
(如果适用)一步完成此更新,但我无法确定 stipulations 的正面或反面符合规范要求。如果有人可以根据上面的示例用一两个示例来消除歧义,那将非常有帮助。
一如既往,非常感谢您的指导和建议:)
你应该清楚地区分映射和元组。 Map
is a key-value structure. Tuple
不是。
:ets
记录是元组,不是映射。
您的初始结构是一个映射元组。一个元组,有很多映射。它作为单个元素插入到 :ets
中,这在您的输出中清晰可见(检查大括号。)
我猜你要将许多个元素插入到缓存中。
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
, as it’s stated in the documentation, returns the first key. :ets.detele/2
通过键 删除记录 并且您的代码将从 :ets.first/1
返回的任何内容包装到一个单元素元组中,使 :ets.delete/2
无论如何都是空操作(是的,:ets.delete/2
总是 returns 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
然后如果你想插入一条新记录,创建一个元组并插入它,不要创建一个包裹在单元素元组中的映射。要通过密钥获取旧记录,通常使用 :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
作为作业离开。