首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ETS表-将地图更新为记录

ETS表-将地图更新为记录
EN

Stack Overflow用户
提问于 2020-06-02 02:06:45
回答 1查看 602关注 0票数 1

样本代码:

代码语言:javascript
复制
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

输出:

代码语言:javascript
复制
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.inspect的说法,old_record已经被删除了,正如tab2list所揭示的那样,这个记录仍然存在。为什么会这样呢?
  2. 实际上,如果old_record从未被删除,那么代码需要进行哪些调整才能完成这一任务?
  3. 理想情况下,我希望使用:ets.select_replace (如果适用的话)在一步内执行此更新,但我不能根据匹配规范的要求确定规定的正面或反面。如果有人能够根据上面的示例用一两个例子来消除歧义,那将是非常有帮助的。

一如既往,非常感谢您的有益指导和建议:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-02 04:43:50

你应该清楚地区分地图和元组。Map是一种键值结构.Tuple不是。

:ets 记录是元组,而不是映射。

您的初始结构是一组地图。一个元组,有很多地图。它作为单个元素插入到:ets中,这在输出中是明显可见的(请检查大括号)。

我猜您将在缓存中插入许多元素。

代码语言:javascript
复制
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返回第一个键。:ets.detele/2按键删除记录,您的代码将从:ets.first/1返回的任何内容封装到一个单元素元组中,使得:ets.delete/2无论如何都成为无操作(是的,:ets.delete/2总是返回true)。

代码语言:javascript
复制
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

代码语言:javascript
复制
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作为作业离开。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62143679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档