Ruby on rails 如何将\u按分组到给定的哈希\u映射中
目前我有两种型号Ruby on rails 如何将\u按分组到给定的哈希\u映射中,ruby-on-rails,ruby,Ruby On Rails,Ruby,目前我有两种型号 class Author # gender # name end class Book # status -> ['published', 'in_progress'] has_one :author end 我决定使用groupby对数据集进行分组 def group_by_gender_by_status books.group_by { |book| [book.author.gender, book.status] } end 我得到的
class Author
# gender
# name
end
class Book
# status -> ['published', 'in_progress']
has_one :author
end
我决定使用groupby
对数据集进行分组
def group_by_gender_by_status
books.group_by { |book| [book.author.gender, book.status] }
end
我得到的是这个
{["male", "published"] => [{BooksRecord}]
["female", "published"] => [{BooksRecord}]
["male", "in_progress"] => [{BooksRecord}]
["female", "in_progress"] => [{BooksRecord}]}
我的目标是得到这个结果
{
female: {
published: 10,
in_progress: 7
},
male: {
published: 6,
in_progress: 9
}
}
这样我就可以通过
数据[:male][:published]
访问,更容易呈现数据我想你可以这样做:
books.group_by { |book| book.author.gender }
.transform_values { |books| books.map(&:status).tally }
特别是,这利用了添加到ruby 2.7版中的可枚举#tally
但是,您没有指定实际使用的是哪个ruby版本,因此如果您使用的是较旧的版本,则可以将最后一行替换为:
.transform_values { |books| books.group_by(&:status).transform_values(&:count) }
我想你可以这样做:
books.group_by { |book| book.author.gender }
.transform_values { |books| books.map(&:status).tally }
特别是,这利用了添加到ruby 2.7版中的可枚举#tally
但是,您没有指定实际使用的是哪个ruby版本,因此如果您使用的是较旧的版本,则可以将最后一行替换为:
.transform_values { |books| books.group_by(&:status).transform_values(&:count) }
Enumerable#group_by
只创建用于分组的键,因此不能专门使用它来生成所需的结果。此外,随着书籍的增长,以这种方式迭代的性能将越来越差
您最好将分组和计数放在数据库上,这样返回的结果更接近您想要的最终结果,如下所示:
def group_by_gender_by_status
books.joins(:author)
.group(Author.arel_attribute(:gender),Book.arel_attribute(:status))
.count
end
这将产生一个与当前的groupby
实现类似的哈希值,但是在返回之前,将在数据库端执行计数和分组:
{["male", "published"] => 6,
["female", "published"] => 10,
["male", "in_progress"] => 9,
["female", "in_progress"] => 7}
要将其转换为所需的嵌套,我们需要对这些数据进行后期处理
def group_by_gender_by_status
books.joins(:author)
.group(Author.arel_attribute(:gender),Book.arel_attribute(:status))
.count
.each_with_object(Hash.new {|h,k| h[k] = {}}) do |((gender,status),counter),obj|
obj[gender.to_sym][status.to_sym] = counter
end
end
最终结果将与您期望的结果相同,通过将分组和计数移动到数据库级别,其降级速度应该会慢得多
注意:我不知道书籍
来自何处,也不知道这种方法目前存在于何处。这种理解可能会进一步减少实现。可枚举#group#U by
只创建分组键,因此不能专门使用它来生成所需的结果。此外,随着书籍的增长,以这种方式迭代的性能将越来越差
您最好将分组和计数放在数据库上,这样返回的结果更接近您想要的最终结果,如下所示:
def group_by_gender_by_status
books.joins(:author)
.group(Author.arel_attribute(:gender),Book.arel_attribute(:status))
.count
end
这将产生一个与当前的groupby
实现类似的哈希值,但是在返回之前,将在数据库端执行计数和分组:
{["male", "published"] => 6,
["female", "published"] => 10,
["male", "in_progress"] => 9,
["female", "in_progress"] => 7}
要将其转换为所需的嵌套,我们需要对这些数据进行后期处理
def group_by_gender_by_status
books.joins(:author)
.group(Author.arel_attribute(:gender),Book.arel_attribute(:status))
.count
.each_with_object(Hash.new {|h,k| h[k] = {}}) do |((gender,status),counter),obj|
obj[gender.to_sym][status.to_sym] = counter
end
end
最终结果将与您期望的结果相同,通过将分组和计数移动到数据库级别,其降级速度应该会慢得多
注意:我不知道书籍
来自何处,也不知道这种方法目前存在于何处。这种理解可能会进一步减少实现。我遵循这种方法。transform|u values{books}books.group|u by(&:status)。transform|u values(&:count)}
因为我的ruby是2.6
,不幸的是它返回的结果是这样的[“男性”,“发布的”=>3,“进行中的”=>10}
我必须做数据[0]==“男性”用于检查其是女性还是男性。感谢各位教授的困惑books=[{BookRecord}]
-->array很难访问data[0]==“male”
和data[1]={:published=>1,:in_progress=>3}
@airsoftwark啊,抱歉,如果我有一点疏忽,但是你可以通过调用.to_h
把它转换成一个好的散列——因为你有成对的值,直接转换是有意义的:我遵循这个方法.transform_values{books}books.group_by(&:status)。transform_values(&:count)}
因为我的ruby是2.6
,不幸的是,它像这样返回“已发布”=>3,“正在进行”=>10}]
我必须做数据[0]='male'来检查它是女性还是男性。感谢各位教授的困惑books=[{BookRecord}]
-->数组很难访问数据[0]==“male”
和数据[1]={:published=>1,:in\u progress=>3}
@airsoftfrack啊,如果我把它弄错了,很抱歉,但是你可以通过调用.to_h
把它转换成一个很好的散列——因为你有成对的值,直接转换是有意义的:您好,谢谢您的回答,我可以在其他地方看到使用这个方法,但是现在我把这个函数放在了Publisher c的一个简单的delegator中lass
而且速度有点慢,因为我需要查询1000个发布者,很抱歉,我没有足够明确地说明question@airsoftFreak我不确定我是否理解您的评论,但是如果书籍
没有加载作者
,您现在处理它的方式将比提案慢得多,并且l导致大量的数据库点击(N+1),因为我已经做了Book.includes(:author)
为了避免N+1,我使用simple delegator进行基本处理,但非常感谢您的帮助Hello感谢您的回答我可以在其他地方看到使用此方法,但目前我将此函数放在Publisher类的simple delegator中
,速度有点慢,因为我需要查询1000个发布者,很抱歉没有关于这个问题要足够明确question@airsoftFreak我不确定我是否理解您的评论,但是如果书籍
没有加载作者
,您现在处理它的方式将比提案慢得多,并且将导致大量数据库点击(N+1),而我已经在做书籍。包括(:author)
为了避免N+1,我使用simple delegator进行基本处理,但非常感谢您的帮助