【发布时间】:2021-03-15 07:42:15
【问题描述】:
我正在努力更新 SVG::Graph gem,并对我的版本进行了许多改进,但发现了多个数组排序的瓶颈。
有一个内置的“sort_multiple”函数,它保持一个数组数组(所有大小相等)按组中的第一个数组排序。
我遇到的问题是这种排序在真正随机的数据上效果很好,在排序或几乎排序的数据上效果很差:
def sort_multiple( arrys, lo=0, hi=arrys[0].length-1 )
if lo < hi
p = partition(arrys,lo,hi)
sort_multiple(arrys, lo, p-1)
sort_multiple(arrys, p+1, hi)
end
arrys
end
def partition( arrys, lo, hi )
p = arrys[0][lo]
l = lo
z = lo+1
while z <= hi
if arrys[0][z] < p
l += 1
arrys.each { |arry| arry[z], arry[l] = arry[l], arry[z] }
end
z += 1
end
arrys.each { |arry| arry[lo], arry[l] = arry[l], arry[lo] }
l
end
此例程似乎使用了来自维基百科的 Lomuto 分区方案的变体:https://en.wikipedia.org/wiki/Quicksort#Lomuto_partition_scheme
我有一个包含 5000 多个数字的数组,它是之前排序的,这个函数在每个图表上增加了大约 1/2 秒。
我已使用以下内容修改了“sort_multiple”例程:
def sort_multiple( arrys, lo=0, hi=arrys[0].length-1 )
first = arrys.first
return arrys if first == first.sort
if lo < hi
...
它已经“修复”了排序数据的问题,但我想知道是否有任何方法可以利用 ruby 内置的更好的排序功能来让这种排序工作得更快。例如你认为我可以利用 Tsort 来加快速度吗? https://ruby-doc.org/stdlib-2.6.1/libdoc/tsort/rdoc/TSort.html
查看我的基准测试,完全随机的第一组似乎非常快。
当前基准测试:
def sort_multiple( arrys, lo=0, hi=arrys[0].length-1 )
if lo < hi
p = partition(arrys,lo,hi)
sort_multiple(arrys, lo, p-1)
sort_multiple(arrys, p+1, hi)
end
arrys
end
def partition( arrys, lo, hi )
p = arrys[0][lo]
l = lo
z = lo+1
while z <= hi
if arrys[0][z] < p
l += 1
arrys.each { |arry| arry[z], arry[l] = arry[l], arry[z] }
end
z += 1
end
arrys.each { |arry| arry[lo], arry[l] = arry[l], arry[lo] }
l
end
first = (1..5400).map { rand }
second = (1..5400).map { rand }
unsorted_arrys = [first.dup, second.dup, Array.new(5400), Array.new(5400), Array.new(5400)]
sorted_arrys = [first.sort, second.dup, Array.new(5400), Array.new(5400), Array.new(5400)]
require 'benchmark'
Benchmark.bmbm do |x|
x.report("unsorted") { sort_multiple( unsorted_arrys.map(&:dup) ) }
x.report("sorted") { sort_multiple( sorted_arrys.map(&:dup) ) }
end
结果:
Rehearsal --------------------------------------------
unsorted 0.070699 0.000008 0.070707 ( 0.070710)
sorted 0.731734 0.000000 0.731734 ( 0.731742)
----------------------------------- total: 0.802441sec
user system total real
unsorted 0.051636 0.000000 0.051636 ( 0.051636)
sorted 0.715730 0.000000 0.715730 ( 0.715733)
#EDIT#
最终接受的解决方案:
def sort( *arrys )
new_arrys = arrys.transpose.sort_by(&:first).transpose
new_arrys.each_index { |k| arrys[k].replace(new_arrys[k]) }
end
【问题讨论】:
-
arrays.transpose.sort_by(&:first).transpose可能值得一试。 -
添加它作为答案,我会支持你!每次操作 0.004 秒 ...唯一(次要)问题是它没有更新原地数组
-
所以问题实际上是如何有效地对我的 SOA 进行排序?
-
可能取决于 SOA 的含义 acronyms.thefreedictionary.com/SOA。
标签: arrays ruby-on-rails ruby sorting