2012-01-19 36 views
3

我有两个阵列a,相同长度的b重新排序以相同的顺序数组作为另一个阵列重新排序

a = [a_1, a_2, ..., a_n] 
b = [b_1, b_2, ..., b_n] 

当我排序a使用sort_by!,的a的元件将被布置在不同的顺序:

a.sort_by!{|a_i| some_condition(a_i)} 

我怎样才能重新排序以相同的顺序/重排的a重新排序b?例如,如果asort_by!

[a_3, a_6, a_1, ..., a_i_n] 

那么我想

[b_3, b_6, b_1, ..., b_i_n] 

编辑

我需要做的很到位(即,保留的a OBJECT_ID,b) 。到目前为止给出的两个答案中给出的排序阵列是有用,:

a_sorted 
b_sorted 

我可以做

a.replace(a_sorted) 
b.replace(b_sorted) 

,但如果可能的话,我想直接做。如果不是,我会接受已经给出的答案之一。

+0

如何为b定义'相同的顺序'?旧索引 - >新索引对于b的每个元素都是等效的? –

+0

@MarkThomas我将它定义为具有相同的置换矩阵(http://en.wikipedia.org/wiki/Permutation_matrix)。 – sawa

+0

您是否需要保存置换矩阵(或向量,因为它可能在这种情况下)? –

回答

10

一种方法是将两个数组压缩在一起并同时进行排序。也许这样的事情?

a = [1, 2, 3, 4, 5] 
b = %w(a b c d e) 

a,b = a.zip(b).sort_by { rand }.transpose 

p a #=> [3, 5, 2, 4, 1] 
p b #=> ["c", "e", "b", "d", "a"] 
+2

+1,'转置'是一个很好的接触! –

+0

你的想法看起来不错,但有没有办法做到这一点?请参阅编辑我的问题。 – sawa

3

如何:

ary_a = [ 3, 1, 2] # => [3, 1, 2] 
ary_b = [ 'a', 'b', 'c'] # => ["a", "b", "c"] 
ary_a.zip(ary_b).sort{ |a,b| a.first <=> b.first }.map{ |a,b| b } # => ["b", "c", "a"] 

ary_a.zip(ary_b).sort_by(&:first).map{ |a,b| b } # => ["b", "c", "a"] 
+0

你的想法看起来不错,但有没有办法做到这一点?请参阅编辑我的问题。 – sawa

2

如果条目是独一无二的,下面可能会工作。我没有测试过它。这部分复制自https://stackoverflow.com/a/4283318/38765

temporary_copy = a.sort_by{|a_i| some_condition(a_i)} 
new_indexes = a.map {|a_i| temporary_copy.index(a_i)} 

a.each_with_index.sort_by! do |element, i| 
    new_indexes[i] 
end 

b.each_with_index.sort_by! do |element, i| 
    new_indexes[i] 
end 
+0

我在想这样的事情,但我不认为Enumerator类具有像map和sort_by这样的方法的就地修改版本。 –

+0

谢谢。像这样做是我想要的。我需要看看使用chron/Tin Man的解决方案与'replace'还是你的答案之间的更快。 – sawa