2012-01-19 1 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)} 

Как я могу изменить порядок b в том же порядке/перегруппировки как переназначения a? Например, если a после sort_by! является

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

я хочу

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

Редактировать

мне нужно сделать это на месте (то есть сохраняют object_id из a, 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

Смежные вопросы