如何在Ruby中按降序排列数组

我有一个哈希数组:

[
{:foo=>'foo',:bar=>2},
{:foo=>'foo',:bar=>3},
{:foo=>'foo',:bar=>5},
]

我试图根据每个散列中:bar的值按降序对该数组进行排序

我正在使用sort\u by对上述数组进行排序:

a.sort_by{h | h[:bar]}

但是,这会按升序对数组进行排序。如何按降序排序

一个解决方案是执行以下操作:

a.sort_by{| h |-h[:bar]}

但这种消极迹象似乎并不恰当

对各种建议答案进行基准测试总是很有启发性的。以下是我发现的:

#!/usr/bin/ruby
要求'基准'
ary=[]
1000.5倍{
ary<{:bar=>兰德(1000)}
}
n=500
Benchmark.bm(20)do|x|
x、 报告("sort"){n.times{ary.sort{a,b{b[:bar]<=>a[:bar]}}
x、 报告("排序反向){n.times{ary.sort{a,b{a[:bar]<=>b[:bar]}.reverse}
x、 报告(“排序依据-a[:bar]”){n.times{ary.sort依据{a}-a[:bar]}}
x、 报告(按a[:bar]*-1排序){n.times{ary.sort{u按a[:bar]*-1}}}
x、 报告(“'sort'u by.reverse!”){n.times{ary.sort'u by{a{a[:bar]}.reverse}
终止
用户系统总真实值
排序3.960000 0.010000 3.970000(3.990886)
反向排序4.040000 0.000000 4.040000(4.038849)
排序依据-a[:bar]0.690000 0.0000000.690000(0.692080)
按[:bar]*-1 0.700000.0000000.700000(0.699735)对_进行排序
按相反顺序排序!0.650000   0.000000   0.650000 (  0.654447)

我认为@Pablo的按{…}排序很有趣。相反是最快的。在运行测试之前,我认为它会比“-a[:bar]”慢,但对该值求反所花费的时间比一次反转整个数组所花费的时间要长。这没什么区别,但每一点加速都会有所帮助


请注意,这些结果在Ruby 1.9中是不同的

以下是Ruby 1.9.3p194(2012-04-20修订版35410)[x86_64-darwin10.8.0]的结果:

用户系统总实际值
分类1.340000 0.010000 1.350000(1.346331)
反向排序1.300000.0000001.300000(1.310446)
排序依据-a[:bar]0.430000 0.000000 0.430000(0.429606)
按[:bar]*-1 0.420000 0.0000000.420000(0.414383)对_进行排序
按相反顺序排序!0.400000   0.000000   0.400000 (  0.401275)

这些都在旧的MacBook Pro上。更新或更快的机器将具有更低的值,但相对差异将保持不变


以下是更新硬件和Ruby 2.1.1版的更新版本:

#/usr/bin/ruby
需要“基准”
放置“正在运行的Ruby#{Ruby_VERSION}”
ary=[]
1000.5倍{
ary<{:bar=>兰德(1000)}
}
n=500
放置“n=#{n}”
Benchmark.bm(20)do|x|
x、 报告(“排序”){n.times{ary.dup.sort{a,b{b[:bar]<=>a[:bar]}
x、 报告(“反向排序”){n.times{ary.dup.sort{a,b{a[:bar]<=>b[:bar]}.reverse}
x、 报告(“按-a[:bar]排序”){n.times{ary.dup.sort_by{a}-a[:bar]}}
x、 报告(“按[:bar]*-1排序”){n次{ary.dup.sort_按{a{a[:bar]*-1}}}
x、 报告(“sort_by.reverse”){n.times{ary.dup.sort_by{a}a[:bar]}.reverse}
x、 报告(“sort_by.reverse!”{n.times{ary.dup.sort_by{a}a[:bar]}.reverse!}
终止
#&gt&燃气轮机;运行Ruby 2.1.1
#&gt&燃气轮机;n=500
#&gt&燃气轮机;用户系统总真实值
#&gt&燃气轮机;排序0.670000 0.0000000.670000(0.667754)
#&gt&燃气轮机;反向排序0.650000 0.0000000.650000(0.655582)
#&gt&燃气轮机;排序依据-a[:bar]0.260000 0.010000 0.270000(0.255919)
#&gt&燃气轮机;按[:bar]*-1 0.250000 0.0000000.250000(0.258924)对_进行排序
#&gt&燃气轮机;按0.250000 0.0000000.250000(0.245179)反向排序
#&gt&燃气轮机;按相反顺序排序!0.240000   0.000000   0.240000 (  0.242340)

在最新的MacBookPro上使用Ruby 2.2.1运行上述代码的新结果。同样,准确的数字并不重要,重要的是它们之间的关系:

运行Ruby 2.2.1的


n=500
用户系统总真实值
排序0.650000 0.0000000.650000(0.653191)
反向排序0.650000 0.0000000.650000(0.648761)
排序依据-a[:bar]0.240000 0.010000 0.250000(0.245193)
按[:bar]*-1 0.240000 0.0000000.240000(0.240541)对_进行排序
按0.230000 0.0000000.230000(0.228571)反向排序
按相反顺序排序!0.230000   0.000000   0.230000 (  0.230040)

在2015年年中的MacBook Pro上更新Ruby 2.7.1:

运行Ruby 2.7.1的


n=500
用户系统总真实值
排序0.494707 0.003662 0.498369(0.501064)
反向排序0.480181 0.005186 0.485367(0.487972)
排序依据-a[:bar]0.121521 0.003781 0.125302(0.126557)
按[:bar]*-10.115097 0.003931 0.119028(0.122991)对_进行排序
按0.110459 0.003414 0.113873(0.114443)排序
按相反顺序排序!0.108997   0.001631   0.110628 (  0.111532)

…reverse方法实际上并不返回一个反向数组-它返回一个枚举数,该枚举数只从末尾开始并向后运行

Array#reverse的源代码是:

静态值
rb_ary_reverse_m(值ary)
{
长透镜=RARRAY_透镜(ary);
值dup=rb_ary_new2(len);
如果(len>0){
常数值*p1=随机常数PTR瞬态(ary);
值*p2=(值*)RARRAY_CONST_PTR_TRANSIENT(dup)+len-1;
do*p2--=*p1++;而(--len>0);
}
ARY_SET_LEN(dup,RARRAY_LEN(ARY));
返回dup;
}

do*p2--=*p1++;而(-len>0)以相反的顺序复制指向元素的指针,因此数组被反转

发表评论