2010-03-24 5 views
-2
@aoaoh; 

$aoaoh[0][0]{21} = 31; 
$aoaoh[0][0]{22} = 31; 
$aoaoh[0][0]{23} = 17; 

for $k (0 .. $#aoaoh) { 
    for $i(0.. $#aoaoh) { 
     for $val (keys %{$aoaoh[$i][$k]}) { 
      print "$val=$aoaoh[$i][$k]{$val}\n"; 
     } 
    } 
} 

Выход:Как я могу отсортировать массив Perl массива хэшей?

 
    22=31 
    21=31 
    23=17 

, но я ожидаю, что это будет

 
    21=31 
    22=31 
    23=17 

Пожалуйста, скажите мне, где это не так.

Кроме того, как сортировать значения, так что я получаю результат, как

 
    23=17 
    22=31 
    21=31 (if 2 keys have same value then key with higher value come first) 
+7

'использовать строги' - пожалуйста! –

ответ

1

Похоже, вы хотите:

for $val (sort keys %{$aoaoh[$i][$k]}) { 

и:

for $val (reverse sort keys %{$aoaoh[$i][$k]}) { 

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

for $val (sort {$aoaoh[$i][$k]->{$a} <=> $aoaoh[$i][$k]->{$b} || $a <=> $b} keys %{$aoaoh[$i][$k]}) { 
+2

Я думаю, что вторая половина его вопроса заключалась в том, как сортировать по значениям, а не по ключам. Просто совпадение было то же, что и порядок обратного ключа. – Will

+0

yes .. Will got me .. Я хочу сортировать его по значениям, а затем, если 2 значения затем сортируют их по убыванию в порядке убывания ... – ksskr

+0

Не могли бы вы рассказать мне, как это сделать? – ksskr

0

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

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

я ожидал бы Tie :: Hash :: индексируются реализация выглядеть так:

my @aoaoh; 

use Tie::Hash::Indexed; 
tie my %hash, 'Tie::Hash::Indexed'; 
$aoaoh[0][0] = \%hash; 

$aoaoh[0][0]{21} = 31; 
$aoaoh[0][0]{22} = 31; 
$aoaoh[0][0]{23} = 17; 

for $k (0 .. $#aoaoh) { 
    for $i(0.. $#aoaoh) { 
     for $val (keys %{$aoaoh[$i][$k]}) { 
      print "$val=$aoaoh[$i][$k]{$val}\n"; 
     } 
    } 
} 
+0

У меня есть массив массивов хешей. Я хочу, чтобы хеши во внутреннем массиве сначала сортировались по их значениям, а когда значения равны, обратные сортируются по их ключам. – ksskr

+0

для $ val (sort {$ aoaoh [ $ i] [$ k] -> {$ a} <=> $ aoaoh [$ i] [$ k] -> {$ b} || $ b <=> $ a} ключи% {$ aoaoh [$ i] [$ k ]}) Решение от Epsilon .. Это то, что я хочу .. но я хочу избежать циклов, так что это альтернатива для этого ... – ksskr

0

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

От perlfaq4 ответ на вопрос How do I sort an array by anything?


Поставка функция сравнения для сортировки() (описано в рода в perlfunc):

@list = sort { $a <=> $b } @list; 

Функция сортировки по умолчанию является CMP, сравнение строк, которые будут сортировать (1, 2, 10) в (1, 10, 2). < =>, используемый выше, является оператором численного сравнения.

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

@idx =(); 
for (@data) { 
    ($item) = /\d+\s*(\S+)/; 
    push @idx, uc($item); 
    } 
@sorted = @data[ sort { $idx[$a] cmp $idx[$b] } 0 .. $#idx ]; 

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

@sorted = map { $_->[0] } 
    sort { $a->[1] cmp $b->[1] } 
    map { [ $_, uc((/\d+\s*(\S+)/)[0]) ] } @data; 

Если необходимо отсортировать по нескольким полям, следующая парадигма является полезным.

@sorted = sort { 
    field1($a) <=> field1($b) || 
    field2($a) cmp field2($b) || 
    field3($a) cmp field3($b) 
    } @data; 

Это удобно сочетать с предварительным расчетом ключей, как указано выше.

Подробнее об этом подходе см. В статье «Больше, чем вы когда-либо хотели знать» в http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz.

См. Также вопрос позже в perlfaq4 по сортировке хешей.

0

Ответ на Q1 будет:

print "${$aoaoh[0][0]}{$_}=$_\n" for sort keys %{$aoaoh[0][0]}; 

, что можно записать в виде:

for (sort keys %{$aoaoh[0][0]}) { 
    print "${$aoaoh[0][0]}{$_}=$_\n" 
} 

И ответ на Q2:

print "$_->[1]=$_->[0]\n" for 
map { [$_->[0], $_->[1]] } 
sort { $a->[0] cmp $b->[0] } 
map { [ ${$aoaoh[0][0]}{$_}, $_ ] } keys %{$aoaoh[0][0]}; 
Смежные вопросы