【问题标题】:Ruby Array group_by key with multiple values具有多个值的 Ruby 数组 group_by 键
【发布时间】:2023-03-13 14:01:01
【问题描述】:

我有一个 Ruby 数组:

[
    {tags: [1,2]},
    {tags: [1,3]},
    {tags: [1,4]},
    {tags: [2,4]},
    {tags: [2,5]}
]

我需要按标签对对象进行分组:

{
    1: [{tags: [1,2]}, {tags: [1,3]}, {tags: [1,4]}],
    2: [{tags: [1,2]}, {tags: [2,4]}, {tags: [2,5]}],
    3: [{tags: [1,3]}],
    4: [{tags: [1,4]}, {tags: [2,4]}],
    5: [{tags: [2,5]}]
}

有没有一种神奇的 Ruby 方法可以做到这一点?

【问题讨论】:

  • 那里有问题吗?您具体遇到了什么问题?
  • @MarkThomas 问题在标题中。给定一个 Hash 元素的 Ruby 数组,我想通过每个 Hash 的 Array 属性中的值来索引这些元素。用文字描述比向您展示代码更难。因此,我提出了一个专注于代码的简洁问题。
  • @MarkThomas,这个问题类似于:“序列 3、9、18、30、45 中的下一个数字是什么?”在我阅读答案之前,我无法弄清楚这个问题。看来如果i 满足h[:tags].include?[i] => true 的至少一个五个哈希h,那么i 是返回的哈希中的一个键,它的值是所有哈希h 的数组,其中h[:tags].include?[i] => true。 (序列中的下一个元素由3(n+n^2)/2 给出。)
  • 不是only将问题放在标题中,而是在问题的正文中重述它。此外,我没有看到任何代码,只有哈希的定义,但没有任何东西可以操纵或创建它。我们需要知道你写了什么来尝试自己解决这个问题。 Stack Overflow 不是“为我编写代码”服务,而是“我编写的代码需要帮助”服务。
  • Stack Overflow 是一个由社区维护/管理的站点,其目标是成为一个类似于维基百科的编程问题和解决方案纲要。因此,我们强烈鼓励遵循这些问题的标准,这些标准可以帮助我们回答问题,而其他正在寻找类似答案的人也会找到这些问题。作为一个在 SO 附近有一段时间的人,我知道这些事情并试图帮助您实现这一目标。

标签: ruby arrays hashtable


【解决方案1】:

使用Enumerable#each_with_object:

tags = [
  {tags: [1,2]},
  {tags: [1,3]},
  {tags: [1,4]},
  {tags: [2,4]},
  {tags: [2,5]}
]
tags.each_with_object(Hash.new { |h,k| h[k] = [] }) { |h, result|
  h[:tags].each { |n| result[n] << h }
}
# => {1=>[{:tags=>[1, 2]}, {:tags=>[1, 3]}, {:tags=>[1, 4]}],
#     2=>[{:tags=>[1, 2]}, {:tags=>[2, 4]}, {:tags=>[2, 5]}],
#     3=>[{:tags=>[1, 3]}],
#     4=>[{:tags=>[1, 4]}, {:tags=>[2, 4]}],
#     5=>[{:tags=>[2, 5]}]}

【讨论】:

  • 很好的答案,感谢您弄清楚所问的内容。
【解决方案2】:

我会这样做:

array = [{tags: [1,2]}, {tags: [1,3]}, {tags: [1,4]}, {tags: [2,4]}, {tags: [2,5]}]

result = Hash.new { |hash, key| hash[key] = [] }

array.each do |tags|
  tags[:tags].each { |tag| result[tag] << tags }
end

puts result
#=> {1=>[{:tags=>[1, 2]}, {:tags=>[1, 3]}, {:tags=>[1, 4]}], 
#    2=>[{:tags=>[1, 2]}, {:tags=>[2, 4]}, {:tags=>[2, 5]}], 
#    3=>[{:tags=>[1, 3]}], 
#    4=>[{:tags=>[1, 4]}, {:tags=>[2, 4]}], 
#    5=>[{:tags=>[2, 5]}]}

【讨论】:

  • 谢谢@spickermann。这与我自己提出的类似,但您将块传递给Hash.new 是一种优雅的感觉。
  • 考虑到您的答案紧随 falsetru 之后,您一定也想通了这个问题。 +1 仅此一项,但答案也很好。
【解决方案3】:

我建议如下:

tags.each_with_object({}) {|g,h| g.values.flatten.each {|i| (h[i]||=[]) << g}}
  #=> {1=>[{:tags=>[1, 2]}, {:tags=>[1, 3]}, {:tags=>[1, 4]}], 
  #    2=>[{:tags=>[1, 2]}, {:tags=>[2, 4]}, {:tags=>[2, 5]}],
  #    3=>[{:tags=>[1, 3]}],
  #    4=>[{:tags=>[1, 4]}, {:tags=>[2, 4]}],
  #    5=>[{:tags=>[2, 5]}]}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-06
    • 2021-08-06
    • 1970-01-01
    • 2012-08-04
    • 2015-01-19
    • 1970-01-01
    • 2014-07-03
    • 2022-01-17
    相关资源
    最近更新 更多