2016-06-30 26 views
0

我读过很多关于使用max和max_by查找数组中值最高的对象的帖子,但是我的情况是更深层次的,我找不到任何有关如何去做的参考。如何返回数组中最高的“值”元素 - 每个“名称” - ?

我有一个实验性的Rails应用程序,我试图转换一个传统的.NET/SQL应用程序。 (简化)模型看起来像Overlay -> Calibration <- Parameter。在单个数据集中,我将拥有20K Calibrations,但其中约3,000-4,000个是通过参数名称进行版本复制的,我只需要每个名称的最高版本参数。更复杂的是,该版本位于Overlay上。 (我知道,这太疯狂了,但这款车型我们的现实。)

在纯SQL,我们下面添加到查询来创建一个虚拟表:

n = ROW_NUMBER() OVER (PARTITION BY Parameters.Designation ORDER BY Overlays.Version DESC) 

,然后选择条目时n = 1

我可以订购该数组是这样的:

ordered_calibrations = mainline_calibrations.sort do |e, f| 
    [f.parameter.Designation, f.overlay.Version] <=> [e.parameter.Designation, e.overlay.Version] || 1 
end 

我得到这种结果:

C_SCR_trc_NH3SensCln_SCRT1_Thd 160 
C_SCR_trc_NH3SensCln_SCRT1_Thd 87 
C_SCR_trc_NH3Sen_DewPtHiThd_Tbl 310 
C_SCR_trc_NH3Sen_DewPtHiThd_Tbl 160 
C_SCR_trc_NH3Sen_DewPtHiThd_Tbl 87 

所以我想知道如果有一种方法,使用Ruby的可枚举内置方法,遍历有序数组,并且只返回每个名称的最高版本元素。如果我可以向此方法的块输入一个整数,并且仅返回版本号最高的元素(“160”将仅返回上面的第二个和第四个条目),则可获得巨大的奖励积分。

替代方案是我可以以某种方式在ActiveRecord中实现ROW_NUMBER() OVER,但是这似乎更难以尝试。当然,我可以编写代码来处理这个问题,但是我相当肯定,如果存在的话,它会比计算正确的Enumerable函数慢几个数量级。 (另外,很明显,做.find_by_sql()并且创建和传统应用程序相同的结果集 - 它甚至很快 - 但我试图拖动所有相关对象你真的不能用这种方法。)

+0

请帮助我们回答您的查询/ help/mcve) –

+0

当你说“参数名称”,你在谈论'Parameters.Designation'? –

回答

1

我不相信在数据库中这样做并不是一个更好的选择,但由于我不熟悉SQL Server,我会给你是Ruby的答案。

我假设当你说“参数名称”时,你说的是Parameters.Designation列,因为这是你的例子中的那个。

您可以直接执行此操作的一种方法是在Ruby 2.2或更高版本中提供Enumerable#slice_whenslice_when当你想切分“不同”值的数组时,它是很好的。例如:

[ { id: 1, name: "foo" }, { id: 2, name: "foo" }, { id: 3, name: "bar" } ] 
    .slice_when {|a,b| a[:name] != b[:name] } 
# => [ [ { id: 1, name: "foo" }, { id: 2, name: "foo" } ], 
#  [ { id: 3, name: "bar" } ] 
# ] 

你已经整理你的收藏,所以要切它,你只需要做到这一点:

calibrations_by_designation = ordered_calibrations.slice_when do |a, b| 
    a.parameter.Designation != b.parameter.Designation 
end 

现在calibrations_by_designation是一个数组的数组,每个从分类最大的Overlay.Version至少。最后一步,那么,是得到的第一个元素中的每一个阵列中:通过写[最小的,完整的和可验证的示例](http://stackoverflow.com

highest_version_calibrations = calibrations_by_designation.map(&:first) 
+0

获取等于或小于某个特定版本号的版本现在已经成为鸡与蛋的问题,但.slice_when()正是我所期待的。谢谢! –

+1

关于速度的说明。我的.find_by_sql()方法使用数据库引擎对所有这些进行排序,AR部分需要2秒,而视图需要3.5秒。使用我非常复杂的AR查找器并使用上面的解决方案对结果进行分类需要4秒AR部分和16秒查看。看起来像拉着所有相关的事情一起骑行可能是站不住脚的。 –

相关问题