5

私は2つの配列を持っています。最初の配列にはソート順が含まれます。2 番目の配列には、任意の数の要素が含まれます。

私は、2 番目の配列のすべての要素 (値に関して) が最初の配列にあることが保証されているというプロパティを持っており、数値のみを扱っています。

A = [1,3,4,4,4,5,2,1,1,1,3,3]
Order = [3,1,2,4,5]

を並べ替えるAと、要素が次のように指定された順序で表示されるようにしますOrder

[3, 3, 3, 1, 1, 1, 1, 2, 4, 4, 4, 5]

複製は公正なゲームであることに注意してください。A の要素は変更しないでください。順序を変更するだけです。これどうやってするの?

4

3 に答える 3

11
>> 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]
于 2012-05-13T18:18:25.890 に答える
4

@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] } 

ベンチマーク:

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)
于 2012-05-13T18:41:16.780 に答える
1

明示的な並べ替えなしの別の可能な解決策:

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)
于 2012-05-14T14:05:57.260 に答える