2012-01-23 6 views
3

У меня есть массив хешей, многие из которых имеют общие ключи.Perl: преобразовать массив хэшей в матрицу

Я хотел бы преобразовать это в матрицу для анализа в [R], так что каждая строка представляет хеш, и каждый уникальный ключ является столбцом, который является (пробелом) или '.' или «NA», если хэш не содержит этот конкретный ключ.

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

Спасибо!

Пример:

my %hash_A = (
    A=> 12, 
    B=> 23, 
    C=> 'a string' 
); 
my %hash_B = (
    B=> 23, 
    C=> 'a different string', 
    D=> 99 
); 

Чтобы дать:

A,B,C,D 
12,23,'a string',NA 
NA, 23, 'a different string', 99 
+1

Не могли бы вы показать небольшой пример вашей структуры данных и желаемый результат? – dgw

+0

Я не пользователь [PDL] (http://pdl.perl.org), но это похоже на то, что я бы предположил, что группа должна будет делать часто и будет иметь простой способ сделать , – Joe

ответ

1

Это должно преобразовать массив хэшей в 2D-массив (@output1).

Все выходные ячейки, в которых не было соответствующего входного значения, будут заполнены 'NA'. (Если вы не возражаете несопоставленные клетки привязываются к undef, то это может быть сделано более лаконично - см @output2.)

Массива @keys будет сказать, какой хэш-ключ относится каждая позиция индекс в выходных строках.

my @array_of_hashes = ...; 

my %keys 

for my $hash (@array_of_hashes) { 
    @keys{keys %$hash} =(); 
} 

my @keys = sort keys %keys; 

my @output1 = map { 
    my $hash = $_; 

    [ map { exists $$hash{$_} ? $$hash{$_} : 'NA' } @keys ]; 
} @array_of_hashes; 

my @output2 = map [ @$_{@keys} ] => @array_of_hashes; 
2

Если вы убедитесь, что каждый из ваших хэшей инициализируются «NA» для каждого возможного ключа, то вы в основном имеют матрицу, и вы может просто распечатать его ... (данные должны быть перезаписаны, если это не «NA»)

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

 
my @possibleKeys = keys %possibleKeys; 
foreach my $hashref (@arrayOfHashes) 
    foreach my $key (@possibleKeys) { 
     if(!defined ${$hashref}{$key}) { 
      print "NA "; 
     else { 
      print "$hashref{$key} "; 
     } 
    print "\n"; 
    } 
} 

Edit: keys %possibleKeys будет возвращать по-разному упорядоченный массив для каждого вызова (см http://perldoc.perl.org/functions/keys.html) для этого ключи должны храниться в массиве, чтобы сохранить порядок.

1
my @a = (keys %hash_A, keys %hash_B); 
my %r; 
@r{@a} = @a; 
for my $h (\%r, \%hash_A, \%hash_B) { 
    print join(', ', map { $$h{$_} ||= 'NA' } sort keys %r), "\n"; 
} 
Смежные вопросы