我有一个哈希数组,我需要根据两个不同的键值对进行排序。
这是我要排序的数组:
array_group = [
{operator: OR, name: "some string", status: false},
{operator: AND, name: "other string", status: false},
{operator: _NOT_PRESENT, name: "another string", status: true},
{operator: AND, name: "just string", status: true}
]
我想对array_group
进行排序,因此我首先包含status: true
的项目,然后是status: false
,然后是operator: _NOT_PRESENT
的项目,最后根据名称对其进行排序,结果如下:
array_group = [
{operator: AND, name: "just string", status: true},
{operator: AND, name: "other string", status: false},
{operator: OR, name: "some string", status: false},
{operator: _NOT_PRESENT, name: "another string", status: true},
]
有没有一种方法可以在不创建子数组并对其进行排序并将它们连接起来的情况下完成此操作?
答案 0 :(得分:5)
您也可以使用Enumerable#sort_by。该示例构建一个数组,在排序时逐个元素进行比较。
array_group.sort_by { |e| [e[:operator] == "_NOT_PRESENT" ? 1 : 0,
e[:status] ? 0 : 1,
e[:name]] }
上面的示例通过operator: "_NOT_PRESENT"
对:status
的记录进行排序。以下代码段精确地执行了问题的排序。
def priority(h)
case
when h[:operator] == "_NOT_PRESENT" then 3
when h[:status] == false then 2
# h[:status] == true
else 1
end
end
array_group.sort_by { |e| [priority(e), e[:name]] }
答案 1 :(得分:1)
您可以使用Array.sort
方法。它接受一个带有两个参数(x,y)的块,当x大于y时它应返回1,否则为-1,如果它们相等则为0。
代码:
OR = "OR"
AND = "AND"
_NOT_PRESENT = "_NOT_PRESENT"
array_group = [
{operator: OR, name: "some string", status: false},
{operator: AND, name: "other string", status: true},
{operator: _NOT_PRESENT, name: "another string", status: true},
{operator: AND, name: "just string", status: true}
]
results = array_group.sort do |x, y|
next x[:operator] == _NOT_PRESENT ? 1 : -1 if x[:operator] == _NOT_PRESENT || y[:operator] == _NOT_PRESENT
next x[:status] ? -1 : 1 if x[:status] != y[:status]
next x[:name] <=> y[:name]
end
顺便说一下,你的输入和输出数据彼此不匹配 - 输入中OR的哈希是false
,输出中是true
。
我相信你的输出应该如下:
[{:operator=>"AND", :name=>"just string", :status=>true},
{:operator=>"AND", :name=>"other string", :status=>true},
{:operator=>"OR", :name=>"some string", :status=>false},
{:operator=>"_NOT_PRESENT", :name=>"another string", :status=>true}]
该输出实际上与您的排序逻辑匹配。
答案 2 :(得分:0)
我假设未指定的常量OR
,AND
和NOT_PRESENT
定义如下(例如):
OR = "or"
AND = "and"
NOT_PRESENT = "not present"
(常量必须以大写字母开头。_NOT_PRESENT
是一个局部变量。)
使用Enumerable#sort_by时,您需要按顺序对包含三个元素的数组进行排序,这三个元素对应:status
,:operator
和:name
。如果0
的值:status
是true
,那么这三个元素中的第一个是最小的(例如1
},如果:status
的值是false
,那么如果是其他任何内容,则2
和最大(例如def rearrange(arr)
arr.sort_by do |h|
[
h[:status]==true ? 0 : (h[:status]==false ? 1 : 2),
(h[:operator]==NOT_PRESENT) ? 0 : 1,
h[:name]
]
end
end
array_group = [
{operator: AND, name: "just string", status: true},
{operator: OR, name: "some string", status: false},
{operator: AND, name: "other string", status: false},
{operator: NOT_PRESENT, name: "another string", status: true},
]
rearrange(array_group)
#=> [{:operator=>"not present", :name=>"another string", :status=>true},
# {:operator=>"and", :name=>"just string", :status=>true},
# {:operator=>"and", :name=>"other string", :status=>false},
# {:operator=>"or", :name=>"some string", :status=>false}]
)。我们有:
def get_model(n):
return make_step(model(n-1))
def make_step(model):
# Compute gradient and make update and return new model
这不是预期的结果,但它符合我对这个问题的理解。
答案 3 :(得分:0)
您可以使用Enumerable#sort_by
使用数组来保留所需的组并按名称排序而不会丢失这些组。
例如:
[[0,0,1], [1,1,1], [0,1,0], [1,0,0], [0,1,1]].sort_by &:itself
# => [[0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 1, 1]]
使用此方法,您可以设置长度为2的数组。使用索引0按所需元素“分组”,索引1按名称排序。
OR = "OR"
AND = "AND"
_NOT_PRESENT = "_NOT_PRESENT"
array_group = [
{ operator: OR, name: "z string", status: false },
{ operator: AND, name: "a string", status: false },
{ operator: AND, name: "z string", status: true },
{ operator: OR, name: "a string", status: true },
{ operator: _NOT_PRESENT, name: "d string", status: true },
{ operator: _NOT_PRESENT, name: "b string", status: true },
{ operator: _NOT_PRESENT, name: "c string", status: false },
{ operator: _NOT_PRESENT, name: "a string", status: false }
]
# Types of "groups" you want to keep. Greater values will be at the end
BY_NOT_PRESENT = 2
BY_STATUS_FALSE = 1
BY_STATUS_TRUE = 0
array_group.sort_by do |a|
group = if a[:operator] == _NOT_PRESENT
BY_NOT_PRESENT
else
a[:status] ? BY_STATUS_TRUE : BY_STATUS_FALSE
end
[group, a[:name]]
end
#=> [{:operator=>"OR", :name=>"a string", :status=>true},
# {:operator=>"AND", :name=>"z string", :status=>true},
# {:operator=>"AND", :name=>"a string", :status=>false},
# {:operator=>"OR", :name=>"z string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"a string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"b string", :status=>true},
# {:operator=>"_NOT_PRESENT", :name=>"c string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"d string", :status=>true}]
我这样做,因为如果只是排序_by像[status, not_present, name]
这样的数组,那么status
将优先于排序,覆盖name
排序,从而导致:
#=> [{:operator=>"OR", :name=>"a string", :status=>true},
# {:operator=>"AND", :name=>"z string", :status=>true},
# {:operator=>"AND", :name=>"a string", :status=>false},
# {:operator=>"OR", :name=>"z string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"b string", :status=>true},
# {:operator=>"_NOT_PRESENT", :name=>"d string", :status=>true},
# {:operator=>"_NOT_PRESENT", :name=>"a string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"c string", :status=>false}]