我已经阅读了很多关于使用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的Enumerable内置方法循环遍历排序的数组,并且只返回每个名称的最高版本元素。如果我可以将一个整数提供给此方法的块,并且只返回最高版本的元素UP to the version version(&#34; 160&#34;将仅返回第二个和第四个条目, )。
替代方案是我可以以某种方式在ActiveRecord中实现ROW_NUMBER() OVER
,但这似乎更难以尝试。当然,我可以编写代码来处理这个问题,但是我很确定它会比确定正确的Enumerable函数(如果存在的话)慢几个数量级。
(另外,要明确的是,执行.find_by_sql()并创建与遗留应用程序相同的结果集 - 它甚至很快 - 但是我很简单试图拖动所有相关的物体,这是你真的可以用这种方法做的。)
答案 0 :(得分:1)
我不相信在数据库中这样做不是更好的选择,但由于我不熟悉SQL Server,我会给你一个Ruby答案。
我假设当您说“参数名称”时,您正在谈论Parameters.Designation
列,因为这是您示例中的那个。
您可以使用Enumerable#slice_when
的一种简单方法,可在Ruby 2.2+中使用。当你想要以某种方式在不同的值之间切换数组时,slice_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
到最少排序。然后,最后一步是获取每个数组中的第一个元素:
highest_version_calibrations = calibrations_by_designation.map(&:first)