Ruby - 查找具有相同属性的所有记录并对其进行分组

时间:2018-03-11 12:38:24

标签: ruby-on-rails ruby database postgresql

如何找到具有相同属性的所有记录并将它们聚集在一起?

示例:动物物种及其类型表。我想聚类相同的物种 IF 它们是相同的类型。或者也许是其他一些属性,比如颜色。因此,如果所有需要的属性不相同,我不想将它们聚类。

展示我不想做的事情的最佳方式是下一个例子:

ID  Species  Type 

0    Bear    Grizzly
1    Wolf    Gray
2    Bear    Grizzly
3    Bear    Polar
4    Wolf    Artic
5    Wolf    Artic
6    Wolf    Gray 

需要的结果:

ID  Species  Type      Cluster_id  

0    Bear    Grizzly    1
1    Bear    Grizzly    1
2    Bear    Polar      2
3    Wolf    Artic      3
4    Wolf    Artic      3
5    Wolf    Gray       4
6    Wolf    Gray       4  

任何想法我怎么能用红宝石写这个?

感谢您的时间。

2 个答案:

答案 0 :(得分:2)

您要找的是group_by,它根据一组属性对所有记录进行分组。例如,假设您的Animal模型具有speciestype属性,则可以根据种类和类型的相似性对所有记录进行分组,如下所示:

Animal.all.group_by { |x| [x.species, x.type] }

或者,您可以首先pluck只需要两个属性,并将结果数组分组为:

Animal.pluck(:species, :type).group_by { |x| [x[0], x[1]] }

结果将是以下形式的哈希:

{
    ["Bear", "Grizzly"] => [["Bear", "Grizzly"], ["Bear", "Grizzly"]], 
    ["Wolf", "Gray"]    => [["Wolf", "Gray"], ["Wolf", "Gray"]], 
    ["Bear", "Polar"]   => [["Bear", "Polar"]], 
    ["Wolf", "Artic"]   => [["Wolf", "Artic"], ["Wolf", "Artic"]]
} 

要将群集信息添加到每条记录,请考虑以下事项。

如果您尚未创建cluster_id字段,可以使用迁移创建它,如下所示:

rails g migration add_cluster_id_to_animals cluster_id:int
rake db:migrate

获得cluster_id字段后,您可以通过迭代group_by创建的哈希来填充它:

hash = Animal.all.group_by { |x| [x.species, x.type] }
hash.each_with_index do |(key,value),index| 
    value.each do |v| 
        v.update_attribute(:cluster_id, index+1)
    end
end

或者,在一行中:

Animal.all.group_by { |x| [x.species, x.type] }.each_with_index {|(key,value),index| value.each {|v| v.update_attribute(:cluster_id, index+1)}}

例如,如果最初您的记录如下所示:

[["Bear", "Grizzly"], 
 ["Wolf", "Gray"], 
 ["Bear", "Grizzly"], 
 ["Bear", "Polar"], 
 ["Wolf", "Artic"], 
 ["Wolf", "Artic"], 
 ["Wolf", "Gray"]]

然后填充cluster_id,您的记录将如下所示:

[["Bear", "Grizzly", 1], 
 ["Wolf", "Gray",    2], 
 ["Bear", "Grizzly", 1], 
 ["Bear", "Polar",   3], 
 ["Wolf", "Artic",   4], 
 ["Wolf", "Artic",   4], 
 ["Wolf", "Gray",    2]]

答案 1 :(得分:1)

如果你不想像其他答案中提到的那样将cluster_id存储在数据库中,你可以按照以下方式为要分组的数组填充它:

原始阵列:

array = [
  ["Bear", "Grizzly"],
  ["Wolf", "Gray"],
  ["Bear", "Grizzly"],
  ["Bear", "Polar"],
  ["Wolf", "Artic"],
  ["Wolf", "Artic"],
  ["Wolf", "Gray"]
] 

这可以按物种分类,生成cluster_id的类型如下:

array.group_by { |x| [x[0], x[1]] }.each.with_index {
  |(key, values), i| values.map! { |x| x << i + 1 }
}

cluster_id值将添加到数组&amp;看起来像:

[
  ["Bear", "Grizzly", 1],
  ["Wolf", "Gray", 2],
  ["Bear", "Grizzly", 1],
  ["Bear", "Polar", 3],
  ["Wolf", "Artic", 4],
  ["Wolf", "Artic", 4],
  ["Wolf", "Gray", 2]
] 

希望它有所帮助!