对于散列哈希数组和自然排序有可行的答案,但是同时进行这两种操作的最佳方法是什么?
my_array = [ {"id":"some-server-1","foo":"bar"},{"id":"some-server-2","foo":"bat"},{"id":"some-server-10","foo":"baz"} ]
Run Code Online (Sandbox Code Playgroud)
我想对"id"进行排序,以便最终的排序是:
some-server-1
some-server-2
some-server-10
Run Code Online (Sandbox Code Playgroud)
我觉得必须有一个聪明有效的方法来做到这一点,虽然我个人不需要打破任何速度记录,只会排序几百项.我可以在sort_by中实现比较功能吗?
首先,你my_array是JavaScript/JSON,所以我假设你真的有这个:
my_array = [
{"id" => "some-server-1", "foo" => "bar"},
{"id" => "some-server-2", "foo" => "bat"},
{"id" => "some-server-10", "foo" => "baz"}
]
Run Code Online (Sandbox Code Playgroud)
然后你只需要值sort_by的数字后缀'id':
my_array.sort_by { |e| e['id'].sub(/^some-server-/, '').to_i }
Run Code Online (Sandbox Code Playgroud)
如果"some-server-"前缀并不总是"some-server-"那么你可以尝试这样的事情:
my_array.sort_by { |e| e['id'].scan(/\D+|\d+/).map { |x| x =~ /\d/ ? x.to_i : x } }
Run Code Online (Sandbox Code Playgroud)
这会将'id'值拆分为数字和非数字片段,将数字片段转换为整数,然后使用Array <=>运算符(比较组件)比较混合字符串/整数数组; 只要数字和非数字组件始终匹配,这将起作用.这种方法可以解决这个问题
my_array = [
{"id" => "some-server-1", "foo" => "bar"},
{"id" => "xxx-10", "foo" => "baz"}
]
Run Code Online (Sandbox Code Playgroud)
但不是这个:
my_array = [
{"id" => "11-pancakes-23", "foo" => "baz"},
{"id" => "some-server-1", "foo" => "bar"}
]
Run Code Online (Sandbox Code Playgroud)
如果您需要处理这最后一种情况,那么您需要手动逐个比较数组,并根据您拥有的内容调整比较.您仍然可以使用类似的东西获得sort_by Schwartzian 变换的一些优点(不是经过良好测试的代码):
class NaturalCmp
include Comparable
attr_accessor :chunks
def initialize(s)
@chunks = s.scan(/\D+|\d+/).map { |x| x =~ /\d/ ? x.to_i : x }
end
def <=>(other)
i = 0
@chunks.inject(0) do |cmp, e|
oe = other.chunks[i]
i += 1
if(cmp == 0)
cmp = e.class == oe.class \
? e <=> oe \
: e.to_s <=> oe.to_s
end
cmp
end
end
end
my_array.sort_by { |e| NaturalCmp.new(e['id']) }
Run Code Online (Sandbox Code Playgroud)
这里的基本思想是将比较噪声推向另一个类,以防止sort_by变形变得难以理解.然后我们使用与以前相同的扫描将字符串分成碎片并<=>手动实现数组比较器.如果我们有两个相同类的东西,那么我们让该类<=>处理它,否则我们强制将两个组件都串起来并比较它们.我们只关心第一个非0结果.
| 归档时间: |
|
| 查看次数: |
844 次 |
| 最近记录: |