【问题标题】:Ruby - How to remove duplicates in array of hashes?Ruby - 如何删除哈希数组中的重复项?
【发布时间】:2018-06-21 11:44:14
【问题描述】:

我在一个哈希数组中有一个哈希数组。我想根据内部数组的值删除重复项。

topics = [{"defense"=>
   [{:id=>30,
     :source=>"Hacker News",
     :title=>
      "China-based campaign breached satellite, defense companies: Symantec",
     :link=>
      "https://www.reuters.com/article/us-china-usa-cyber/china-based-campaign-breached-satellite-defense-companies-symantec-idUSKBN1JF2X0"}]},
 {"companies"=>
   [{:id=>30,
     :source=>"Hacker News",
     :title=>
      "China-based campaign breached satellite, defense companies: Symantec",
     :link=>
      "https://www.reuters.com/article/us-china-usa-cyber/china-based-campaign-breached-satellite-defense-companies-symantec-idUSKBN1JF2X0"}]},
 {"Symantec"=>
   [{:id=>30,
     :source=>"Hacker News",
     :title=>
      "China-based campaign breached satellite, defense companies: Symantec",
     :link=>
      "https://www.reuters.com/article/us-china-usa-cyber/china-based-campaign-breached-satellite-defense-companies-symantec-idUSKBN1JF2X0"}]}]

topics.uniq { |phrase, post| post }
puts topics

您可以在上面看到短语 defensecompaniesSymantec 每个都包含相同的数组。我怎样才能只保留包含一个相同数组的第一个哈希?

预期输出:

{"defense"=>
  [{:id=>30,
    :source=>"Hacker News",
    :title=>
     "China-based campaign breached satellite, defense companies: Symantec",
    :link=>
     "https://www.reuters.com/article/us-china-usa-cyber/china-based-campaign-breached-satellite-defense-companies-symantec-idUSKBN1JF2X0"}]}

注意:在上面的例子中,每个“短语”的内部数组只包含一个哈希,但在应用程序中它可以包含多个帖子。

【问题讨论】:

  • 如果您删除那些额外的数组,即topics = {"defense" => { id: 30, ... }, "companies" => { id: 30, ...}},处理数据可能会更容易。只是说;-)
  • @stefan 有没有办法可以做到这一点并保持每个短语包含多个帖子的能力?在上面的示例中,我只展示了一篇与“防御”短语相关的文章,但实际上该短语下可能有多个帖子。
  • 那么您可以拥有{"defense" => [{...}, {...}], "companies" => [...] },但无需将每个短语-帖子对包装在单独的哈希中。似乎topics 应该是单个哈希,topics.keys 返回["defense", "companies", "Symantec"]
  • 也许您可以将您的示例更多地调整为实际值,即添加一些所有短语共有的帖子和其他独特的帖子。然后显示您的预期结果。也许您可以减少示例数据的数量,例如只要有:id 和一个简短的:title
  • 如果主题值超过 1 项会怎样? Array 应该是唯一的还是生成的 Hash 应该只出现 1 次任何值?现在,当完整的 Array 被认为是唯一性的价值和要求时,这将起作用。 topics.map(&:values).uniq.map {|v| topics.find {|h| h.values == v } }。但是,可以通过将reduce(&:merge) 链接到末尾来转换为Hash,但是如果一个键在具有不同值的主题中出现超过1 次,则将这个Array 转换为Hash 似乎适得其反

标签: arrays ruby


【解决方案1】:

topics.invert.invert 会将散列减少为每个唯一值的单个(任意选择)键。

【讨论】:

  • 不幸的是,topics 是一个数组,其值分布在不同的散列中。
  • 啊..topics.inject(:merge).invert.invert? ://
  • 这不会是任意的,它将是最后一个结果获胜,在这种情况下将是"Symantec" 而不是"defense",因为问题表明结果应该是
【解决方案2】:

使用此解决方案,您只能得到数组:

topics.map { |topic| topic.values }.uniq.flatten 

它只返回:

# => [{:id=>30, :source=>"Hacker News", :title=>"China-based campaign breached satellite, defense companies: Symantec", :link=>"https://www.reuters.com/article/us-china-usa-cyber/china-based-campaign-breached-satellite-defense-companies-symantec-idUSKBN1JF2X0"}]

【讨论】:

    【解决方案3】:
    topics = [
      { "defense"   => [{ id: 30, source: "Hacker", title: "China", link: "F2X0"}] },
      { "companies" => [{ id: 30, source: "Hacker", title: "China", link: "F2X0"}] },
      { "Symantec"  => [{ id: 30, source: "Hacker", title: "China", link: "F2X0"}] }
    ]
    
    topics.uniq { |h| h.values }
      #=> [{"defense"=>[{:id=>30, :source=>"Hacker", :title=>"China", :link=>"F2X0"}]}]
    

    请参阅Array#uniq 以了解uniq 使用块的情况。注意这句话,“self按顺序遍历,第一次出现的保留。”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2018-07-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多