2009-04-13 2 views
5

Я хочу сортировать хэш, который на самом деле имеет хэш в качестве значения. Например:Как я могу сортировать хэш хэшей по ключу в Perl?

my %hash1=(
    field1=>"", 
    field2=>"", 
    count=>0, 
); 
my %hash2; 
$hash2{"asd"}={%hash1}; 

и я вставил много хешей к %hash2 с различными значениями количества в %hash2.

Как я могу сортировать %hash1 в соответствии со значением счета hash1?

Есть ли способ сделать это без реализации quicksort вручную, например, с функцией сортировки Perl?

+0

ли вы имеете в виду, что вы хотите получить список хэшей (как hash1), отсортированных по графу из значений в hash2? – Jagmal

+0

yes Jagmal, что означает, что я хочу сортировать по отношению к $ hash2 {"asd"} {count}. – systemsfault

ответ

10
my @hash1s = sort {$a->{count} <=> $b->{count}} values %hash2; 
+0

Я пробовал этот путь, но получаю следующее предупреждение: [предупреждение]: использование неинициализированного значения в числовом сравнении (<=>) на – systemsfault

+0

Отрывок из кода как для моего ответа, так и для моего комментария к вашему ответу, работают для меня при тестировании (даже с -w и «использовать строгий»). –

+0

вы получаете это предупреждение, потому что один или несколько ваших хэшей не имеют значения для ключа «count». Если вы хотите считать их 0, вы можете сделать сортировку {($ a -> {count} || 0) <=> ($ b -> {count} || 0)} values% hash2; – nohat

1

Если вы хотите, чтобы получить список хэшей (как hash1), отсортированных по графу из значений в hash2, это может помочь:

@sorted_hash1_list = sort sort_hash_by_count_key($a, $b) (values (%hash2); 


# This method can have any logic you want 
sub sort_hash_by_count_key { 
    my ($a, $b) = @_; 
    return $a->{count} <=> $b->{count}; 
} 
+0

Вы хотите сказать «sort \ & sort_hash_by_count_key, values% hash2» вместо того, что у вас есть? –

+0

Я предполагаю, что это тоже будет работать, не так ли? – Jagmal

0

Смотрите http://perldoc.perl.org/functions/sort.html для Лота контекста хау сортировки работ в Perl.

И вот пример .. пытаясь быть читаемым, а не perlish.

#!/usr/bin/perl 
# Sort Hash of Hashes by sub-hash's element count. 
use warnings; 
use strict; 


my $hash= { 
      A=>{C=>"D",0=>"r",T=>"q"} 
      ,B=>{} 
      ,C=>{E=>"F",G=>"H"} 
      }; 

sub compareHashKeys {0+(keys %{$hash->{$a}}) <=> 0+(keys %{$hash->{$b}}) } 

my @SortedKeys = sort compareHashKeys keys %{$hash}; 
print join ("," , @SortedKeys) ."\n"; 
+0

Что такое '0+'? – systemsfault

+0

Предполагается, что значение 0+ должно умножать значение на число, однако <=> уже делает это, поэтому 0+ действительно избыточно. :-P –

+0

Ну, значение, которое выходит из cmp или <=>, уже является числовым, равным -1, 0 или 1. Не имеет значения, каковы данные. sort() нуждается в -1, 0 или 1, чтобы решить, как упорядочить вещи. –

6

От perlfaq4, ответ на "http://faq.perl.org/perlfaq4.html#How_do_I_sort_a_hash" имеет большую часть информации, которую нужно собрать свой код.

Возможно, вы также захотите ознакомиться с разделом «Сортировка» в Изучение Perl.

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

my @sorted_hashes = 
    sort { $hash2->{$a}{count} <=> $hash2->{$b}{count} } 
    keys %hash2; 

я сделать это таким образом, потому что это немного меньше галлюциногенный ,


Как отсортировать хэш (необязательно по значению вместо ключа)?

(отвечает Брайан Д. Фой)

Для сортировки хэш, начните с ключами. В этом примере мы приводим список ключей функции сортировки, который затем сравнивает их ASCIIbetically (на которые могут влиять ваши настройки локали). Выходной список имеет ключи в ASCII-битезированном порядке. Когда у нас есть ключи, мы можем пройти через них, чтобы создать отчет, в котором перечислены ключи в ASCII-виде.

my @keys = sort { $a cmp $b } keys %hash; 

foreach my $key (@keys) 
    { 
    printf "%-20s %6d\n", $key, $hash{$key}; 
    } 

Мы могли бы получить больше причуд в блоке sort(). Вместо сравнения ключей мы можем вычислить значение с ними и использовать это значение в качестве сравнения.

Например, чтобы сделать наш запрос нечувствительным к регистру, мы используем последовательность \ L в строке с двумя кавычками, чтобы сделать все в нижнем регистре. Затем блок sort() сравнивает нижние значения, чтобы определить, в каком порядке положить ключи.

my @keys = sort { "\L$a" cmp "\L$b" } keys %hash; 

Примечания: если вычисление дорого или хэш имеет много элементов, вы можете захотеть взглянуть на Шварц Transform для кэширования результатов вычислений.

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

my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash; 

Оттуда мы можем усложниться. Если значения хэша одинаковы, мы можем предоставить вторичный вид хэш-ключа.

my @keys = sort { 
    $hash{$a} <=> $hash{$b} 
     or 
    "\L$a" cmp "\L$b" 
    } keys %hash; 
+0

wow большое объяснение thanx. – systemsfault

0

Для сортировки по числовому использованию < => и для использования в строке cmp.

# sort by the numeric count field on inner hash 
# 
foreach my $key (sort {$hash2{$a}->{'count'} <=> $hash2{$b}->{'count'}} keys %hash2) { 
    print $key,$hash2{$key}->{'count'},"\n"; 
} 

# sort by the string field1 (or field2) on the inner hash 
# 
foreach my $key (sort {$hash2{$a}->{'field1'} cmp $hash2{$b}->{'field1'}} keys %hash2) { 
    print $key,$hash2{$key}->{'field1'},"\n"; 
} 

Чтобы изменить порядок просто поменять местами $ а и $ Ь:

# sort by the numeric count field on inner hash 
# 
foreach my $key (sort {$hash2{$a}->{'count'} <=> $hash2{$b}->{'count'}} keys %hash2) { 
    print $key,$hash2{$key}->{'count'},"\n"; 
} 

# sort by the string field1 (or field2) on the inner hash 
# 
foreach my $key (sort {$hash2{$a}->{'field1'} cmp $hash2{$b}->{'field1'}} keys %hash2) { 
    print $key,$hash2{$key}->{'field1'},"\n"; 
} 
Смежные вопросы