Ruby on rails 在多个条件下使用max_by的有效方法
我一直在想如何在多种条件下使用Ruby on rails 在多个条件下使用max_by的有效方法,ruby-on-rails,ruby,sorting,Ruby On Rails,Ruby,Sorting,我一直在想如何在多种条件下使用max\u by和max方法。虽然我认为我做到了,但经过广泛的测试,结果证明并非如此 例如,我有一个值为哈希的哈希: chapters = { "686050": { "volume": '1', "chapter": '1', "title": 'Chapter Title', "lang_code": 'gb', "timestamp": 1_565_434_815 },
max\u by
和max
方法。虽然我认为我做到了,但经过广泛的测试,结果证明并非如此
例如,我有一个值为哈希的哈希:
chapters = { "686050": {
"volume": '1',
"chapter": '1',
"title": 'Chapter Title',
"lang_code": 'gb',
"timestamp": 1_565_434_815
},
"686049": {
"volume": '2',
"chapter": '1',
"title": 'Chapter Title',
"lang_code": 'gb',
"timestamp": 1_565_300_815
},
"686048": {
"volume": '2',
"chapter": '2',
"title": 'Chapter Title',
"lang_code": 'gb',
"timestamp": 1_565_300_815
}
}
我想找到一个散列,它有最大的卷和章节。所以在本例中,我希望得到第二卷和第二章的内容
我的第一个实现是使用max
:
chapters.max do | a,b|
a[1][:卷].至\u d b[1][:卷].至\u d&&
a[1][:章].至d b[1][:章].至d
结束
当我看到这一点时,我的想法是,它将首先按体积进行比较,然后按章节进行比较。这个代码已经起作用了。。。直到我将哈希更改为:
“686050”:{
“卷”:“1”,
“第章”:“1”,
“标题”:“章节标题”,
“语言代码”:“gb”,
“时间戳”:1_565_434_815
},
"686049": {
“卷”:“2”,
“第章”:“1”,
“标题”:“章节标题”,
“语言代码”:“gb”,
“时间戳”:1_565_300_815
}
它突然开始返回第一卷和第二章!我仍然不确定为什么会发生这种情况
所以我决定尝试max_by
,使用这个chapters.max_by{| |,v | v[:volume].to|d&&v[:chapter].to|d}
,使用相同的假设。当每卷只有一章时,它也以失败告终
我的解决方案是:
章节
.group_by{|,v | v[:volume].to|d}.max.last.to|h
.max_by{|,v | v[:章].to|d}
这样做的原因很明显,但感觉效率很低。必须有一种方法使用单个
max
或max\u by
。希望听到一些关于这方面的想法您可以执行以下操作
def max_val(h,key)
h.map { |_,g| g[key] }.max
end
max_volume = max_val(h, :volume) #=> "2"
max_chapter = max_val(h, :chapter) #=> "2"
chapters.find { |_,g| g[:volume] == max_volume && g[:chapter] == max_chapter }
#=> [:"686048", {:volume=>"2", :chapter=>"2", :title=>"Chapter Title",
# :lang_code=>"gb", :timestamp=>1565300815}]
如果没有值包含两个键的最大值,则返回nil
。如果要返回具有所需属性的所有键值对(即,如果存在连接),则将find
替换为select
。如果没有值包含两个键的最大值,则该数组将为空
这需要三次通过散列。它可以在一个过程中完成,但它很混乱,我希望它会更耗时,主要是因为Enumerable#map
和Array#max
都是用C实现的
一次通过即可获得预期结果,如下所示
max_volume = 0.chr
max_chapter = 0.chr
candidate = [nil, {}]
chapters.each do |k,g|
old_max_volume = max_volume
max_volume = [max_volume, g[:volume]].max
old_max_chapter = max_chapter
max_chapter = [max_chapter, g[:chapter]].max
if max_volume > old_max_volume || max_chapter > old_max_chapter
candidate = (max_volume == g[:volume] && max_chapter == g[:chapter]) ?
[k,g] : [nil, {}]
end
end
candidate
#=> [:"686048", {:volume=>"2", :chapter=>"2", :title=>"Chapter Title",
# :lang_code=>"gb", :timestamp=>1565300815}]
现在设定:
chapters[:"686048"][:volume] = '1'
上面的第一个方法现在返回nil
,第二个(一次通过)返回[nil,{}]
#示例1
a=%w[信天翁狗马]
a、 max|u by(2){| x | x.length}#=>[“信天翁”,“马”]
#示例2-以“元素方式”比较数组
数组=['1','1'],['2','1'],['2','2']]
arrays.max_by(2){arr{arr}}}=>[“2”,“2”],[“2”,“1”]
所以
chapters.max_by{| | |,elem |[elem[:volume],elem[:chapter]}
让我们测试一下
book1={
"686050": {
“卷”:“1”,
“第章”:“1”,
“标题”:“章节标题”,
“语言代码”:“gb”,
“时间戳”:1_565_434_815
},
"686049": {
“卷”:“2”,
“第章”:“1”,
“标题”:“章节标题”,
“语言代码”:“gb”,
“时间戳”:1_565_300_815
},
"686048": {
“卷”:“2”,
“章节”:“2”,
“标题”:“章节标题”,
“语言代码”:“gb”,
“时间戳”:1_565_300_815
}
}
第二册={
"686050": {
“卷”:“1”,
“第章”:“1”,
“标题”:“章节标题”,
“语言代码”:“gb”,
“时间戳”:1_565_434_815
},
"686049": {
“卷”:“2”,
“第章”:“1”,
“标题”:“章节标题”,
“语言代码”:“gb”,
“时间戳”:1_565_300_815
}
}
pp book1.max_by(2){| |,elem |[elem[:volume],elem[:chapter]}
pp book2.max_by{| | |,elem |[elem[:volume],elem[:chapter]}
输出
# 1st test
[[:"686048",
{:volume=>"2",
:chapter=>"2",
:title=>"Chapter Title",
:lang_code=>"gb",
:timestamp=>1565300815}],
[:"686049",
{:volume=>"2",
:chapter=>"1",
:title=>"Chapter Title",
:lang_code=>"gb",
:timestamp=>1565300815}]]
# 2nd test
[:"686049",
{:volume=>"2",
:chapter=>"1",
:title=>"Chapter Title",
:lang_code=>"gb",
:timestamp=>1565300815}]
我相信你不会反对我的编辑。我主要添加了变量
h
来保存你的散列,这样读者就可以在答案和评论中引用该变量,而无需对其进行定义。一点也不@CarySwoveland,尽管我会将其编辑为章节,因为这是我使用的,也是我的代码块中引用的。我相信你的代码有问题。请看我对@calvin答案的评论。如果您按照我的建议在修改book2
后设置chapters=book2
,您的代码返回[:“686049”、{:volume=>“2”、:chapter=>“1”、:title=>“chapter title”、:lang_code=>“gb”、:timestamp=>1565300815}]
,我认为这不符合您的要求。假设您的book2
更改如下:book2[:“686050”][:chapter]=“2”
。然后book2.max\u通过{| |,elem{elem[:volume],elem[:chapter]}=>[:“686049”,{:volume=>“2”,…]
,但这是不正确的,因为h
的任何值都不包含:volume
的最大值和:chapter
的最大值。是的,也有绑定的书籍。因此,在此之前有一个步骤,即按时间戳对书籍进行排序,以便max_按选择第一个,即最新上载的。是的,这一关看起来一团糟。对我来说可读性比性能更重要,所以你的第一个建议很好。不过我可能会坚持我的建议,因为它更简洁,即使还有几步