gpt4 book ai didi

Ruby 对不同数据类型按多字段多方向排序

转载 作者:数据小太阳 更新时间:2023-10-29 07:44:58 25 4
gpt4 key购买 nike

我需要编写一个multi_sort 方法来对接受散列作为参数的散列数组进行排序,例如:{ a_sort: 1, display_sort: 1 }。这个散列是排序字段和排序方向。 (1表示升序,-1表示降序)。

items = [ {name: 'Album 1', a_sort: 5, display_sort: 3}, 
{name: 'Album 2', a_sort: 1, display_sort: 5},
{name: 'Album 3', a_sort: 3, display_sort: 2},
{name: 'Album 5', a_sort: 1, display_sort: 8},
{name: 'Album 7', a_sort: 5, display_sort: 1},
{name: 'Album 7', a_sort: 5, display_sort: 6} ]

multi_sort(items, {a_sort: 1, display_sort: 1})

3 小时后我无法弄清楚。预期输出是正确排序的数组。

      [ {name: 'Album 2', a_sort: 1, display_sort: 5},
{name: 'Album 5', a_sort: 1, display_sort: 8},
{name: 'Album 3', a_sort: 3, display_sort: 2},
{name: 'Album 7', a_sort: 5, display_sort: 1}
{name: 'Album 1', a_sort: 5, display_sort: 3},
{name: 'Album 7', a_sort: 5, display_sort: 6} ]

最佳答案

非常有趣的问题。我也认为 sort_by方法将是最有帮助的。我的解决方案(仅适用于数值)是这样工作的:

DIRECTION_MULTIPLIER = { asc: 1, desc: -1 }

def multi_sort(items, order)
items.sort_by do |item|
order.collect do |key, direction|
item[key]*DIRECTION_MULTIPLIER[direction]
end
end
end

# ... items ...
multi_sort(items, a_sort: :asc, display_sort: :desc)

想法是为 sort_by 传递的每个项目构建一个列表.该列表包含所有已给出排序顺序的值。因此,我们使用 Ruby 知道 [1,2]小于 [1,3]但大于 [0,0] .

需要注意的一个有趣部分是函数的最后一个参数将作为一个散列传递,并且这些散列对的顺序将保持。哈希中的这种“有序”行为不一定适用于所有语言,但 Ruby documentation状态:Hashes enumerate their values in the order that the corresponding keys were inserted .

-- 编辑更通用 --

因为,chamnap 要求一个更通用的解决方案,它适用于任意数据类型和 nil ,这里有一个更全面的解决方案,它依赖于 <=>运算符(operator):

require 'date'
DIRECTION_MULTIPLIER = { asc: 1, desc: -1 }

# Note: nil will be sorted towards the bottom (regardless if :asc or :desc)
def multi_sort(items, order)
items.sort do |this, that|
order.reduce(0) do |diff, order|
next diff if diff != 0 # this and that have differed at an earlier order entry
key, direction = order
# deal with nil cases
next 0 if this[key].nil? && that[key].nil?
next 1 if this[key].nil?
next -1 if that[key].nil?
# do the actual comparison
comparison = this[key] <=> that[key]
next comparison * DIRECTION_MULTIPLIER[direction]
end
end
end

我正在使用 sort方法。每次排序函数需要与元素进行比较时,都会调用该 block 。该 block 应为相应的对返回 -1、0 或 1(按顺序更小、等于或更高)。在这个排序 block 中,我正在浏览 order hash 包含项目中散列值的键和方向。如果我们发现了较早的顺序差异(例如,第一个键更高),我们就返回该值。如果过去的比较结果相同,我们使用 <=>运算符比较传递给排序 block 的两个元素(如果我们想要降序,则将结果乘以 -1)。唯一烦人的是处理nil values,它在实际比较之上添加了三行。

这是我的测试代码:

items = [ {n: 'ABC  ', a:   1, b: Date.today+2},
{n: 'Huhu ', a: nil, b: Date.today-1},
{n: 'Man ', a: nil, b: Date.today},
{n: 'Woman', a: nil, b: Date.today},
{n: 'DEF ', a: 7, b: Date.today-1}]
multi_sort(items, b: :asc, a: :desc, n: :asc)

更一般的说明:由于排序逻辑变得有点复杂,我会将数据包装在具有属性的实际对象中。然后你可以覆盖 <=>运算符如图所示 here .

关于Ruby 对不同数据类型按多字段多方向排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28234803/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com