Как использовать map (), чтобы применить операцию к каждому элементу хэша в Perl? - PullRequest
2 голосов
/ 22 октября 2009

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

foreach my $key ( keys( %{$results} ) ) {
   $results->{$key}{uri} =~ s/\".*\/(.*\.*(gif|jpe?g|png))\"/\/resources\/uploads\/$1/gi;
}

$ results - это возврат из хеш-функции с помощью функции DBI fetchall_hashref().

Просто из любопытства я хотел посмотреть, смогу ли я переписать его, используя вместо этого map(), как показано ниже:

map {
   $results{$_}{uri} =~ s/\".*\/(.*\.*(gif|jpe?g|png))\"/\/resources\/uploads\/$1/gi
} keys %{$results};

К сожалению, это не работает. Я перепробовал все что угодно, но пока безуспешно. Кто-нибудь знает, как это сделать? Спасибо.

UPDATE

Исправленный код, на который отвечает ysth :

map {
   $results->{$_}{uri} =~ s/\".*\/(.*\.*(gif|jpe?g|png))\"/\/resources\/uploads\/$1/gi
} keys %{$results};

и улучшенная версия с меньшим количеством зубочисток , предложенная Sinan Ünür

map {
   $results->{$_}{uri} =~ s{".*/(.*\.*(gif|jpe?g|png))"}{/resources/uploads/$1}gi
} keys %{$results};

Ответы [ 3 ]

10 голосов
/ 22 октября 2009

Стоит отметить, что вы могли бы сойти с рук

$_->{uri} =~ s/foo/bar/ for values %$results;

в этом случае. Работа в структуре данных не мешает ссылкам, которые ее составляют.

8 голосов
/ 22 октября 2009

В версии карты вы по ошибке изменили $results->{ на $results{. Вставьте -> обратно, и оно должно работать.

5 голосов
/ 22 октября 2009

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

use warnings;
use strict;

my $results = {
    a => {uri => "\"c/x.png\"" },
    b => {uri => "\"d/y.jpeg\""}
};

map {
   $results->{$_}{uri} =~ 
       s/\".*\/(.*\.*(gif|jpe?g|png))\"/\/resources\/uploads\/$1/gi
} keys %{$results};

for my $k (keys %$results) {
    print "$k $results->{$k}{uri}\n";
}
...