繁体   English   中英

ETS 表 - 将地图更新为记录

[英]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}}
]

观察/问题:

  1. 根据IO.inspectold_record已被删除,正如tab2list显示的那样,该记录仍然存在。 这是为什么?
  2. 实际上,如果old_record从未被删除,那么代码需要进行哪些调整才能完成此操作?
  3. 理想情况下,我想利用: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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM