如何根据属性附加一个唯一的结构数组?

How to append a unique array of struct based on an attribute?

我有一个结构数组,我需要根据属性使它们保持唯一,:num。该数组将附加新的结构对象。如果新结构对象有一个重复的:num属性,我想删除包含重复:num的旧元素并用新元素替换它。

这就是我的意思。让我们设置它:

Gen = Struct.new(:num, :val)
arr = []
arr << Gen.new(11, "foo1")
arr << Gen.new(12, "foo2")

# [#<struct num=11, val="foo1">, #<struct num=12, val="foo2">]

然后我用新的结构喂它。让我们构建它们:

s1 = Gen.new(12, "foo10")
s2 = Gen.new(13, "foo3")

s1 附加到 arr 时,它需要替换旧的 #<struct num=12, val="foo2"> 结构,因为 s1 是最新的提要。由于 arr 已经包含 :num 12,我们需要用新结构替换它。由于 s2 包含一个唯一的 :num,它应该能够被追加没问题(即使 s2 包含一个重复的 :val,也没关系,我只是担心保持 :num 独特)。

最后,我需要arr看起来像:

[#<struct num=11, val="foo1">, #<struct num=12, val="foo10">, #<struct num=13, val="foo3">]

数组的顺序无关紧要。

我查看了 Add element to an array if it's not there already, 从 Ruby 中的数组中删除重复元素 ,以及其他一些帖子。它们主要处理简单数组,而不是结构数组。

我怎样才能做到这一点?

把新的 gen 一个接一个。找到对应的old gen,让它拥有new one的值。如果没有找到老一代,添加完整的新一代。

Gen = Struct.new(:num, :val) 
arr = []
arr << Gen.new(11, "foo1")
arr << Gen.new(12, "foo2")

new_gens = [Gen.new(12, "foo10"),
            Gen.new(13, "foo3")]
#let's go
new_gens.each do |new_gen|
  match = arr.detect{|old_gen| old_gen.num == new_gen.num}
  match ? match.val = new_gen.val : arr << new_gen
end
  
p arr # =>[#<struct num=11, val="foo1">, #<struct num=12, val="foo10">, #<struct num=13, val="foo3">]

维护一个散列是最简单的,其键是 :num 的值,其值是关联的结构。哈希 (h) 可以按如下所需方式使用新结构 (st) 进行更新。

def add_struct(h, st)
  h.update(st[:num]=>st)
end

然后当需要当前结构数组时,只需 return 散列值。

参见 Hash#update(又名 merge!)。回想一下,如果哈希 hg 都有一个键 k,则哈希 h.update(g)(或 h.merge(g))中 k 的值等于g[k]。对于 h.update({ st[:num]=>st })h.update(st[:num]=>st) 是 shorthand。 add_struct的return值是h的更新值。

这是一个例子。

Gen = Struct.new(:num, :val)
s1 = Gen.new(11, "foo1")
  #=> #<struct Gen num=11, val="foo1">
s2 = Gen.new(12, "foo2")
  #=> #<struct Gen num=12, val="foo2">
s3 = Gen.new(12, "foo10")
  #=> #<struct Gen num=12, val="foo10">
s4 = Gen.new(13, "foo3")
  #=> #<struct Gen num=13, val="foo3">
h = {}
add_struct(h, s1)
  #=> {11=>#<struct Gen num=11, val="foo1">}
add_struct(h, s2)
  #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo2">}
add_struct(h, s3)
  #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo10">}
add_struct(h, s4) 
  #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo10">,
  #    13=>#<struct Gen num=13, val="foo3">}
h #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo10">,
  #    13=>#<struct Gen num=13, val="foo3">} 
h.values
  #=> [#<struct Gen num=11, val="foo1">,
  #    #<struct Gen num=12, val="foo10">,
  #    #<struct Gen num=13, val="foo3">]