【问题标题】:How to append a unique array of struct based on an attribute?如何根据属性附加一个唯一的结构数组?
【发布时间】:2021-11-10 02:42:11
【问题描述】:

我有一个结构数组,我需要根据属性:num 保持它们的唯一性。该数组将附加新的结构对象。如果新的 struct 对象有重复的: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")
  • 如果我使用arr &lt;&lt; s1,它只会将s1 附加到arr 中。
  • 如果我在执行上述操作后执行arr.uniq {|el| el.number},有时会删除“foo10”,但我希望始终保留最新的结构。

s1 附加到arr 时,它需要替换旧的#&lt;struct num=12, val="foo2"&gt; 结构,因为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 alreadyRuby condition for inserting unique items into an arrayRemove duplicate elements from array in Ruby 和其他一些帖子。他们都主要处理简单的数组,而不是结构数组。

我怎样才能做到这一点?

【问题讨论】:

  • 好收获!已编辑:)
  • 这里有Array 的要求吗?您可以实现自己的集体类并在内部使用核心枚举。我个人推荐Hash

标签: arrays ruby struct append unique


【解决方案1】:

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

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

然后,当需要当前结构的数组时,只需返回哈希值。

Hash#update(又名merge!)。回想一下,如果哈希 hg 都有一个键 k,则哈希 h.update(g)(或 h.merge(g))中的 k 的值等于 g[k]h.update(st[:num]=&gt;st)h.update({ st[:num]=&gt;st }) 的简写。 add_struct的返回值是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">]

【讨论】:

  • 我认为有一个错字。而不是h.update(st=&gt;st[:num]),我认为应该是h.update(st[:number]=&gt;st)。除此之外,很好的解决方案。谢谢!
  • Iggy,感谢您的提醒。我在测试中更正了这一点,但忘记在我的答案中进行更正。
【解决方案2】:

把新的gens 一个一个拿。找到对应的老一代,让它拥有新的价值。如果没有找到旧代,则添加完整的新代。

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">]

【讨论】:

  • 在我的用例中,我没有将其投票为接受的答案 bc 我的结构中有更多属性。另一个答案更容易。但是,我对此表示赞成,因为 sln 在技术上适用于我在帖子中给出的示例。谢谢!
猜你喜欢
  • 1970-01-01
  • 2022-12-09
  • 2019-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-25
  • 1970-01-01
相关资源
最近更新 更多