有这样的代码。在其中,按对象名称对数组进行排序。
但是麻烦的是,例如,如果不是 first_name 或 last_name ,则为 nil,false 。
那是一个错误。 错误是:比较Array和Array失败。
array.sort_by do |item|
if item.expression
[item.title, item.description]
else
[item.first_name, item.last_name]
end
end
如何针对这种情况安全地分类?
[item.title || 0, item.description || 0]
我认为这样做不是专业的。有什么好主意吗?
答案 0 :(得分:1)
(注意:我不明白您的意思是“ first_name
,而last_name
可能是false
”。听起来不对,不是我。我要假设它们可能是nil
,而不是false
。)
要获得快速,简单的解决方法,您可以将nil
的值强制转换为String
s,例如:
array.sort_by do |item|
if item.expression
[String(item.title), String(item.description)]
else
[String(item.first_name), String(item.last_name)]
end
end
这几乎等于 说“按字母顺序排序; nil
最后一个”。
它不能区分""
和nil
这两个值。如果要使排序的这一方面更加严格,则需要编写something more custom, using the <=>
operator。
答案 1 :(得分:0)
有两种方法可以做到这一点。首先,让我们创建一些数据。
Items = Struct.new(:expression, :title, :description, :first_name, :last_name)
values =
[[false, 'x', 'x', 'Bob', nil],
[true, 'Nine Lives', 'Cat story', 'x', 'x'],
[false, 'x', 'x', 'Mary', 'Tuffet'],
[false, 'x', 'x', false, 'Cocker'],
[false, 'x', 'x', 'Lois', 'Lane'],
[false, 'x', 'x', 'Bob', 'Newhart'],
[true, 'Death Comes Calling', 'Who done it', 'x', 'x'],
[false, 'x', 'x', 'Mary', 'Martin']]
array = values.map { |a| Items.new(*a) }
注意:
array.map do |item|
[item.expression, item.title, item.description, item.first_name, item.last_name]
end == values
#=> true
分区,排序和连接
goodies, baddies = array.partition { |item|
item.expression || (item.first_name && item.last_name) }
a = goodies.sort_by do |item| item.expression ? [item.title, item.description] :
[item.first_name, item.last_name]
end.concat(baddies)
a.map do |item|
[item.expression, item.title, item.description, item.first_name, item.last_name]
end
#=> [[false, "x", "x", "Bob", "Newhart"],
# [true, "Death Comes Calling", "Who done it", "x", "x"],
# [false, "x", "x", "Lois", "Lane"],
# [false, "x", "x", "Mary", "Martin"],
# [false, "x", "x", "Mary", "Tuffet"],
# [true, "Nine Lives", "Cat story", "x", "x"],
# [false, "x", "x", "Bob", nil],
# [false, "x", "x", false, "Cocker"]]
最后两个元素放在最后。前面的元素按以下顺序排序:
["Bob", "Newhart"]
["Death Comes Calling", "Who done it"]
["Lois", "Lane"]
["Mary", "Martin"]
["Mary", "Tuffet"]
["Nine Lives", "Cat story"]
b = array.sort do |item1, item2|
if item1.expression==false && !(item1.first_name && item1.last_name)
1
elsif item2.expression==false && !(item2.first_name && item2.last_name)
-1
else
(item1.expression ? [item1.title, item1.description] :
[item1.first_name, item1.last_name]) <=>
(item2.expression ? [item2.title, item2.description] :
[item2.first_name, item2.last_name])
end
end
b.first(6) == a.first(6)
#=> true
a
和b
的最后两个元素包含相同的两个元素,但顺序不同。由于未指定这些元素的顺序,因此应该没有问题。