2010-08-01 4 views
2

У меня есть несколько массивов одинаковой длины. Я хочу отсортировать первый массив и сделать все остальные массивы «сортировкой» соответственно. Например, если первый массив равен (7,2,9), второй - ("seven","two","nine"), а третий - ("VII","II","IX") после сортировки (по возрастанию согласно первым значениям массива), мы будем иметь (2,7,9)("two","seven","nine") и ("II","VII","IX").Как вы сортируете параллельные массивы в Perl?

Как я могу это сделать?

+0

Я бы использовал сложную структуру данных для этих данных (массив массивов, массив хашей или, возможно, хэш массивов/Hashe с). – MvanGeest

ответ

5

реорганизовать данные в единый массив для сортировки:

my @a = ([7, "seven", "VII"], [2, "two", "II"], ..); 
@a = sort { $a->[0] <=> $b->[0] } @a; 

Затем воссоздать исходные массивы:

my(@a1, @a2, @a3); 

for (@a) { 
    push @a1, shift @$_; 
    push @a2, shift @$_; 
    push @a3, shift @$_; 
} 
4

Как обнаруживает, поддерживая параллельные массивы может быть хлопоты и ошибки склонный. Альтернативный подход заключается в том, чтобы сохранить взаимосвязанную информацию вместе.

use strict; 
use warnings; 

# One array-of-hashes instead of three parallel arrays. 
my @numbers = (
    { arabic => 7, text => 'seven', roman => 'VII' }, 
    { arabic => 2, text => 'two', roman => 'II' }, 
    { arabic => 9, text => 'nine', roman => 'IX' }, 
); 

@numbers = sort { $a->{arabic} <=> $b->{arabic} } @numbers; 
17

Хотя я согласен с Женей у и MvanGeest, что обычно лучший ответ должен переключиться на другую структуру данных, иногда вы можете хотите параллельные массивы (или, по крайней мере, не может быть в состоянии избежать их), и на самом деле является способом параллельного параллельного параллельного массива. Это выглядит следующим образом:

my @nums = (7, 2, 9); 
my @names = qw(seven two nine); 
my @roman = qw(VII II IX); 

my @sorted_indices = sort { $nums[$a] <=> $nums[$b] } 0..$#nums; 
@$_ = @{$_}[@sorted_indices] for \(@nums, @names, @roman); 

То есть, создать список из индексов, которые соответствуют всем массивам, а затем отсортировать их в соответствии с порядком, в котором будет «первичным» массив в порядке. Когда у нас есть отсортированный список индексов, переупорядочивайте все массивы, чтобы они совпадали.

Последняя строка может быть записан в обычное письме

@nums = @nums[@sorted_indices]; 
@names = @names[@sorted_indices]; 
@roman = @roman[@sorted_indices]; 

, но я пытался уменьшить количество копий пасты необходима, даже цену некоторых слегка волосатого синтаксиса. Больше, что вы знаете ...

+1

+1 Slick. Предлагает идею общей функции в этих строках: 'sub sort_parallel_arrays {my ($ comparator, @arrays) = @_; ...} '. – FMc

+0

+1 Очень здорово! –

6

Я знаю, что вы уже приняли ответ, и есть другие действительно хорошие ответы здесь, но я бы предложил что-то другое: не дублируйте свои данные . Вам нужно всего лишь отслеживать арабское -> римское сопоставление - почему хранить то, что по существу дублирует массивы чисел, и сортировать все? Просто сортировать основной список и посмотреть другие значения в опорном массиве при необходимости:

my @roman = qw(0 I II III IV V VI VII VIII IX X); 
my @text = qw(zero one two three four five six seven eight nine ten); 

my @values = (7, 2, 9); 
my @sorted_values = sort @values; 
my @sorted_roman = map { $roman[$_] } @sorted_values; 
my @sorted_text = map { $text[$_] } @sorted_values; 

use Data::Dumper; 
print Dumper(\@sorted_values, \@sorted_roman, \@sorted_text); 

принтов:

$VAR1 = [ 
      2, 
      7, 
      9 
     ]; 
$VAR2 = [ 
      'II', 
      'VII', 
      'IX' 
     ]; 
$VAR3 = [ 
      'two', 
      'seven', 
      'nine' 
     ]; 

В реальных условиях, я предложил бы использовать библиотеки для выполнения Roman и текстовые конверсии для вас:

use Roman; 
my @sorted_roman = map { roman($_) } @sorted_values; 

use Lingua::EN::Numbers 'num2en'; 
my @sorted_text = map { num2en($_) } @sorted_values; 
+0

+1: Это очень похоже на предложение hobbs, но с более сильным синтаксисом, не так ли? –

+2

@ Давид: не совсем; Подход hobbs по-прежнему хранит списки номеров в каждом формате, сортирует числовые, а затем использует индексы тех, которые являются ориентиром для сортировки других. Я полностью отказываюсь от хранения списков других значений и просто просматриваю их из главной таблицы преобразования (или внешнего модуля преобразования). Если вы сортируете вещи, которые нужно сортировать в одно и то же время, но вы не можете легко конвертировать их из одного в другое (т. Е. Вам нужно хранить обе версии), подход hobbs - это путь, но в противном случае используйте таблица поиска. – Ether

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