【问题标题】:Erlang - String into SetErlang - 字符串到集合
【发布时间】:2021-11-09 01:12:00
【问题描述】:

当我在 String Anagrams 上计算 Sets 时,我目前正在尝试了解 Erlang Sets 的行为。在我的理解中,两个 Anagrams 应该产生两个相同的字符串集合。

Set1 = sets:from_list("orchestra"). 
Set2 = sets:from_list("carthorse"). 
Set1 =:= Set2. %% true

但是,使用sets:intersection,我们会收到一个不同的集合,它不等于前两个集合。

Intersection = sets:intersection(Set1, Set2). 
Intersection =:= Set1. %% false
Intersection =:= Set2. %% false

根据 Erlang 中 Set-Intersections 的计算方式,这种行为是否有特殊原因? 非常感谢!

【问题讨论】:

    标签: erlang


    【解决方案1】:

    =:= 运算符比较 Set1Intersection 的表示,但不能保证表示是什么或同一集合只有一种表示。

    sets 的文档在描述它如何比较集合的元素而不是集合本身时只讨论了=:=

    对于集合相等,你可以定义

    set_eq(S1, S2) ->
        sets:is_subset(S1, S2) andalso sets:is_subset(S2, S1).
    

    【讨论】:

      【解决方案2】:

      sets 模块的实现不保证两个集合可以与=:= 进行比较,即使它们包含相同的元素。内部数据结构可以不同。您可以使用is_subset/2subtract/2 之类的操作(效率相对较低),或者您可以使用to_list/1 然后lists:sort/1 来获得两个可以直接比较的列表。但是,如果您是从字符串(字符列表)开始,最好立即使用ordsets。这些是有序列表,您可以将其作为集合进行操作,并且可以直接进行比较。对于小型集,它们通常比sets 更有效。

      > Set1 = ordsets:from_list("orchestra").
      "acehorst"
      > Set2 = ordsets:from_list("carthorse").
      "acehorst"
      > Set1 =:= Set2.
      true
      > Intersection = ordsets:intersection(Set1, Set2).
      "acehorst"
      > Intersection =:= Set1.
      true
      > Intersection =:= Set2.
      true
      

      【讨论】:

      • 感谢您对 ordsets 的推荐,这正是我想要的!来自 Clojure,我期望的行为类似于 (= (set "carthorse") (clojure.set/intersection (set "orchestra") (set "carthorse")) ) => true
      【解决方案3】:

      让我们看看代码,看看沿途发生了什么。

      我们定义了 2 个集合

      Set1 = sets:from_list("orchestra"). 
      {set,8,16,16,8,80,48,
           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
           {{[],"sc",[],[],[],"o","r","e","h",[],[],"a","t",[],[],[]}}}
      

      Set2 = sets:from_list("carthorse"). 
      {set,8,16,16,8,80,48,
           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
           {{[],"sc",[],[],[],"o","r","e","h",[],[],"a","t",[],[],[]}}}
      
      

      其中第二行表示使用表示创建的值。所以根据上面的定义,我们推断存储集合所选择的表示是一个元组。

      我们可以参考 Erlang 参考手册的 Term Comparison 部分,其中指出

      ...Lists are compared element by element. Tuples are ordered by size, two tuples with the same size are compared element by element...

      将其作为不变量,现在让我们看看在intersection 之后出现的集合

      Intersection = sets:intersection(Set1, Set2).
      {set,8,16,16,8,80,48,
           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
           {{[],"cs",[],[],[],"o","r","e","h",[],[],"a","t",[],[],[]}}}
      

      同样,这是一个集合,它得到元组的相同底层表示,但如果我们查看最后一个元素,有一个字符串(本质上是 Erlang 中的字符列表)"cs",它的值在当我们定义Set1Set2 时在同一个地方。因此根据Term Comparison 的不等式。

      现在,让我们尝试将Intersection 中的子值"cs" 更改为"sc",然后根据Term Comparison 规则,两个集合必须满足相等。

      Improvised_Intersection = setelement(9, Intersection, {setelement(2, element(1, element(9, Intersection)), "sc")}).
      {set,8,16,16,8,80,48,
           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
           {{[],"sc",[],[],[],"o","r","e","h",[],[],"a","t",[],[],[]}}}
      

      现在让我们将Improvised_IntersectionSet1Set2 进行比较,得到

      Improvised_Intersection =:= Set1.                                                                                  
      true
      
      Improvised_Intersection =:= Set2.                                                                                  
      true
      
      Intersection =:= Improvised_Intersection.
      false
      

      这只是试图对@Richard 和其他人已经指出的内容提供一些见解。

      【讨论】:

      • 只是我们的好奇心,当(单个)字符列表分别映射到值“cs”或“sc”时,幕后会发生什么。这是哈希函数的结果吗?
      • 你可能是完全正确的。根据sets,地图在幕后发挥作用
      猜你喜欢
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-03
      相关资源
      最近更新 更多