为了对数组 Error: java.io.IOException: Response code: 400 Error response:
{"name":"TRANSACTION_REFUSED","message":"The request was refused.
{0}","information_link":"https://developer.paypal.com/webapps/developer/docs/api/#
TRANSACTION_REFUSED","debug_id":"e4334e766671"}
的字符串进行降序排序,可以使用a
。
reverse
但是当您想在多个排序键中使用字符串时,无法完成。假设a.sort.reverse
是包含属性items
(attr1
),String
(attr2
),String
(attr3
的项目数组})。排序可以像:
Integer
可以通过将items.sort_by{|item| [item.attr1, item.attr2, item.attr3]}
与Integer
相乘,为-1
独立完成从上升到下降的切换:
items.sort_by{|item| [item.attr1, item.attr2, -item.attr3]}
但String
这种方法并不简单。可以定义这样的方法吗?如果您想对attr2
进行降序排序,则应该写成:
items.sort_by{|item| [item.attr1, item.attr2.some_method, item.attr3]}
答案 0 :(得分:2)
以下内容支持响应<=>
的所有对象。
def generalized_array_sort(arr, inc_or_dec)
arr.sort do |a,b|
comp = 0
a.zip(b).each_with_index do |(ae,be),i|
next if (ae<=>be).zero?
comp = (ae<=>be) * (inc_or_dec[i]==:inc ? 1 : -1)
break
end
comp
end
end
实施例
arr = [[3, "dog"], [4, "cat"], [3, "cat"], [4, "dog"]]
inc_or_dec = [:inc, :dec]
generalized_array_sort(arr, inc_or_dec)
#=> [[3, "dog"], [3, "cat"], [4, "dog"], [4, "cat"]]
另一个例子
class A; end
class B<A; end
class C<B; end
[A,B,C].sort #=> [C, B, A]
arr = [[3, A], [4, B], [3, B], [4, A], [3, C], [4,C]]
inc_or_dec = [:inc, :dec]
generalized_array_sort(arr, inc_or_dec)
#=> [[3, A], [3, B], [3, C], [4, A], [4, B], [4, C]]
答案 1 :(得分:2)
我不确定其中任何一个都通过了您的直截了当测试,但我认为两者都能正常工作。使用@ CarySwoveland的测试数据:
arr = [[3, "dog"], [4, "cat"], [3, "cat"], [4, "dog"]]
arr.sort_by {|a, b| [ a, *b.codepoints.map(&:-@) ] }
# => [[3, "dog"], [3, "cat"], [4, "dog"], [4, "cat"]]
或者,这里的解决方案无论类型如何都有效(即它不必是字符串):
arr.sort do |a, b|
c0 = a[0] <=> b[0]
next c0 unless c0.zero?
-(a[1] <=> b[1])
end
# => [[3, "dog"], [3, "cat"], [4, "dog"], [4, "cat"]]
后者可以概括为如下方法:
def arr_cmp(a, b, *dirs)
return 0 if a.empty? && b.empty?
return a <=> b if dirs.empty?
a0, *a = a
b0, *b = b
dir, *dirs = dirs
c0 = a0 <=> b0
return arr_cmp(a, b, *dirs) if c0.zero?
dir * c0
end
这就像<=>
一样,但是它的最终参数采用1
或-1
的列表来指示每个相应数组元素的排序方向,例如:
a = [3, "dog"]
b = [3, "cat"]
arr_cmp(a, b, 1, 1) # => 1
arr_cmp(a, b, 1, -1) # => -1
与<=>
类似,它在sort
块中最有用:
arr.sort {|a, b| arr_cmp(a, b, 1, -1) }
# => [[3, "dog"], [3, "cat"], [4, "dog"], [4, "cat"]]
尽管如此,我还没有对它进行过多次测试,因此可能存在失败的边缘情况。
答案 2 :(得分:2)
我认为您始终可以将字符串转换为整数数组(ord
)。像这样:
strings = [["Hello", "world"], ["Hello", "kitty"], ["Hello", "darling"]]
strings.sort_by do |s1, s2|
[
s1,
s2.chars.map(&:ord).map{ |n| -n }
]
end
PS:
正如@CarySwoveland在这里发现的是一个带有空字符串的角落案例,这可以通过这个非优雅的解决方案来解决:
strings.sort_by do |s1, s2|
[
s1,
s2.chars.
map(&:ord).
tap{|chars| chars << -Float::INFINITY if chars.empty? }.
map{ |n| -n }
]
end
并且@Jordan善意地提到sort_by使用Schwartzian Transform因此您根本不需要预处理。
答案 3 :(得分:1)
虽然我不知道通用的学术实施,但在现实生活中我会选择:
class String
def hash_for_sort precision = 5
(@h_f_p ||= {})[precision] ||= self[0...precision].codepoints.map do |cp|
[cp, 99999].min.to_s.ljust 5, '0'
join.to_i
end
end
现在可以按-item.attr2.hash_for_sort
排序。
上述方法存在一些问题:
> precision
字母不同的字符串进行有效排序; O(self.length)
; 但考虑到真正的情况,我无法想象何时这还不够。
P.S。如果我要精确地解决这个问题,我会搜索一个算法,以一对一的方式将字符串转换为浮点数。