[英]Sort an array of numbers based on a given order
I have two arrays. 我有两个数组。 The first array contains the sort order.
第一个数组包含排序顺序。 The second array contains an arbitrary number of elements.
第二个数组包含任意数量的元素。
I have the property that all elements (value-wise) from the second array are guaranteed to be in the first array, and I am only working with numbers. 我有一个属性,保证第二个数组中的所有元素(按值)保证在第一个数组中,我只使用数字。
A = [1,3,4,4,4,5,2,1,1,1,3,3]
Order = [3,1,2,4,5]
When I sort A
, I would like the elements to appear in the order specified by Order
: 当我对
A
排序时,我希望这些元素按Order
指定的Order
:
[3, 3, 3, 1, 1, 1, 1, 2, 4, 4, 4, 5]
Note that duplicates are fair game. 请注意,重复是公平的游戏。 The elements in A should not be altered, only re-ordered.
A中的元素不应更改,只能重新排序。 How can I do this?
我怎样才能做到这一点?
>> source = [1,3,4,4,4,5,2,1,1,1,3,3]
=> [1, 3, 4, 4, 4, 5, 2, 1, 1, 1, 3, 3]
>> target = [3,1,2,4,5]
=> [3, 1, 2, 4, 5]
>> source.sort_by { |i| target.index(i) }
=> [3, 3, 3, 1, 1, 1, 1, 2, 4, 4, 4, 5]
If (and only if!) @Gareth's answer turns out to be too slow, instead go with: 如果(并且只有!)@ Gareth的答案结果太慢了,而是选择:
# Pre-create a hash mapping value to index once only…
index = Hash[ Order.map.with_index.to_a ] #=> {3=>0,1=>1,2=>2,4=>3,5=>4}
# …and then sort using this constant-lookup-time
sorted = A.sort_by{ |o| index[o] }
Benchmarked: 基准测试:
require 'benchmark'
order = (1..50).to_a.shuffle
items = 1000.times.map{ order.sample }
index = Hash[ order.map.with_index.to_a ]
Benchmark.bmbm do |x|
N = 10_000
x.report("Array#index"){ N.times{
items.sort_by{ |n| order.index(n) }
}}
x.report("Premade Hash"){ N.times{
items.sort_by{ |n| index[n] }
}}
x.report("Hash on Demand"){ N.times{
index = Hash[ order.map.with_index.to_a ]
items.sort_by{ |n| index[n] }
}}
end
#=> user system total real
#=> Array#index 12.690000 0.010000 12.700000 ( 12.704664)
#=> Premade Hash 4.140000 0.000000 4.140000 ( 4.141629)
#=> Hash on Demand 4.320000 0.000000 4.320000 ( 4.323060)
Another possible solution without explicit sorting: 没有明确排序的另一种可能的解
source = [1,3,4,4,4,5,2,1,1,1,3,3]
target = [3,1,2,4,5]
source.group_by(&lambda{ |x| x }).values_at(*target).flatten(1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.