Как я могу напечатать содержимое хэша в Perl?

167

Я продолжаю печатать свой хэш как количество выделенных сегментов. Как мне распечатать содержимое моего хэша?

Без использования whileцикла было бы наиболее предпочтительным (например, однострочник будет лучше).

Кыс
источник

Ответы:

253

Data :: Dumper - твой друг

use Data::Dumper;
my %hash = ('abc' => 123, 'def' => [4,5,6]);
print Dumper(\%hash);

будет выводить

$VAR1 = {
          'def' => [
                     4,
                     5,
                     6
                   ],
          'abc' => 123
        };
Tetromino
источник
3
оригинальный постер может также захотеть изучить различные опции Data :: Dumper, в частности, включение 'Sortkeys' может быть очень полезным
plusplus
1
@JonathanDay Мне не хватало этой детали, и это было полезно! Спасибо!
Сос
5
Что значит добавить косую черту перед%?
шампунь
16
@shampoo slash operator создает ссылку, немного похожую на &операторы в C и C ++. Причина, по которой это имеет значение в этом контексте, заключается в том, что в Perl, если вы вызываете функцию со значением хеш-функции в качестве аргумента, это значение хеш-функции будет распечатано и разбито на несколько аргументов - так %hsh=("a" => 1, "b" => 2); foo(%hsh);что будет эквивалентно foo("a", 1, "b", 2). Если вы хотите, чтобы функция работала с самим хэшем, вам нужно передать ссылку на хеш: foo(\%hsh);См. Perldoc.perl.org/perlsub.html#Pass-by-Reference
tetromino
63

Легко:

print "$_ $h{$_}\n" for (keys %h);

Элегантно, но на самом деле на 30% медленнее (!):

while (my ($k,$v)=each %h){print "$k $v\n"}
Джонатан Грал
источник
9
Слезы: напечатайте "@_ \ n", в то время как @_ = каждый% h
FMC
Я думаю, что вы имеете в виду print "$_ $h{$_}\n" for (keys %h);, $kне существует в этом примере.
час. Оуэнс
4
Кроме того, сравните результаты, прежде чем делать заявления об эффективности (или хотя бы определите тип эффективности, о котором вы говорите). forЦикл быстрее , чем whileдо , по меньшей мере 10000 ключей: gist.github.com/151792
Chas. Оуэнс
1
Конечно, вы правы: $ k. Но это более эффективно в Perl 6! :) Да, вы тоже правы в этом. Я бы никогда не подумал оптимизировать или профилировать свой Perl, но я рад этому научиться. Конечно, каждый из них должен быть более эффективным (потому что нет никакого дополнительного поиска хеша на ключе). Но это на 30% медленнее!
Джонатан Грел
Привет, Джонатан Грэл. Извините, до сих пор не понимаю. Вы говорите, что каждый из них на 30% медленнее? Всегда ли для каждой ситуации разрыв составляет 30%?
Карлос Са
37

Вот как вы можете печатать без использования Data::Dumper

print "@{[%hash]}";
Тим Дикманн
источник
24

В целях отладки я буду часто использовать YAML.

use strict;
use warnings;

use YAML;

my %variable = ('abc' => 123, 'def' => [4,5,6]);

print "# %variable\n", Dump \%variable;

Результаты в:

# %variable
---
abc: 123
def:
  - 4
  - 5
  - 6

В других случаях я буду использовать Data::Dump. Вам не нужно устанавливать столько переменных, чтобы вывести его в хорошем формате, чем вы делаете Data::Dumper.

use Data::Dump = 'dump';

print dump(\%variable), "\n";
{ abc => 123, def => [4, 5, 6] }

Совсем недавно я использовал Data::Printerдля отладки.

use Data::Printer;
p %variable;
{
    abc   123,
    def   [
        [0] 4,
        [1] 5,
        [2] 6
    ]
}

(Результат может быть намного более красочным на терминале)

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

use strict;
use warnings;

use MTie::Hash;
use Data::Printer;

my $h = tie my %h, "Tie::StdHash";
@h{'a'..'d'}='A'..'D';
p %h;
print "\n";
p $h;
{
    a   "A",
    b   "B",
    c   "C",
    d   "D"
} (tied to Tie::StdHash)

Tie::StdHash  {
    public methods (9) : CLEAR, DELETE, EXISTS, FETCH, FIRSTKEY, NEXTKEY, SCALAR, STORE, TIEHASH
    private methods (0)
    internals: {
        a   "A",
        b   "B",
        c   "C",
        d   "D"
    }
}
Брэд Гилберт
источник
иметь аккуратные цвета, но я либо делаю что-то не так, либо использую «use Data :: Printer; p% var;» не печатает стрелки в хешах, и для такого новичка, как я, это помогает
Sos
@Sosi Если вы посмотрите на вывод в ответе, вы увидите, что он не выводит то, =>что вы ожидаете. Вместо этого он всегда печатает ключ, несколько пробелов, а затем значение. Что помогает человеку сканировать вывод.
Брэд Гилберт
12

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

print map { "$_ $h{$_}\n" } keys %h;

или

print "$_ $h{$_}\n" for keys %h;

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

Из-за того, что Data::Dumperявляется частью базовой библиотеки Perl, она, вероятно, самая популярная; Тем не менее, некоторые другие модули могут предложить очень хорошие вещи.

Чес. Owens
источник
10

Мой любимый: Smart :: Комментарии

use Smart::Comments;
# ...

### %hash

Вот и все.

лесоруб
источник
5
Извините, но я голосую за материал, который перехватывает комментарии для реальной функциональности. Программист обслуживания мог потратить весь день, пытаясь понять, почему такой код печатает неожиданные вещи.
MikeKulls
2
@MikeKulls, нп. Это фильтр источника, так что я понимаю. Кроме того, написав сценарии, которые проверяют каждый модуль, который я включил в производственную подготовку use Smart::Comments, я не вижу его с этой точки зрения. Но для счетчика, Smart::Commentsон довольно хорошо ведет себя как модуль с областью видимости , не должно быть выходного поведения в любом модуле, который также не использует SC. Таким образом, проблема будет изолирована для этих областей с помощью оператора использования . Если вы говорите, что программист по техническому обслуживанию не несет ответственности за чтение документации по включенным модулям, я не могу согласиться. Тем не менее, спасибо за комментарий
Axeman
7
Я не говорю, что они не несут ответственности, но вряд ли это будет первое, что они ищут. Я никогда раньше не видел модуль Smart Comments, и я бы не знал, почему вышеприведенный код что-то печатал. Я мог тратить дни на пропуск комментария и даже не обрабатывать его, потому что комментарии ничего не должны делать. Заставить их сделать что-то очень плохо, имо. Их можно использовать для создания документации и т. Д., Если они не изменяют поведение программы.
MikeKulls
4

Циклический:

foreach(keys %my_hash) { print "$_ / $my_hash{$_}\n"; }

функциональная

map {print "$_ / $my_hash{$_}\n"; } keys %my_hash;

Но для чистой элегантности я должен был бы выбрать Wrang-Wrang. Для моего собственного кода я бы выбрал свой foreach. Или использовать самосвал тетро.

Пол Натан
источник
3
Там нет функциональной разницы между вашим использованием foreachи map. mapдолжен использоваться для преобразования списка, а не в пустом контексте для эмуляции цикла for
friedo
было бы интересно увидеть результаты каждого из байт-кода ... Интересно, более ли менее эффективна карта.
Обезьяна
2

Самый простой способ в моем опыте - просто использовать Dumpvalue .

use Dumpvalue;
...
my %hash = { key => "value", foo => "bar" };
my $dumper = new DumpValue();
$dumper->dumpValue(\%hash);

Работает как шарм, и вам не нужно беспокоиться о форматировании хэша, поскольку он выводит его, как это делает отладчик Perl (отлично подходит для отладки). Кроме того, Dumpvalue включен в стандартный набор модулей Perl, так что вам не придется связываться с CPAN, если вы находитесь за каким-то драконовским прокси (как я на работе).

Weegee
источник
1

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

print Dumper( { 'abc' => 123, 'def' => [4,5,6] } );

Не делать ничего особенного, кроме использования анонимного хеша для пропуска временной переменной;)

Кайл Уолш
источник
ОП говорит, что у него есть «мой хэш», который нужно распечатать. Этот ответ является просто
умом
ОП надеялся сделать это в одну строку. Просто показывал способ сделать это одной строкой. Так что это достойно отрицательного голоса?
Кайл Уолш
1

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

print map {$_ . " "} %h, "\n";
carlos_lm
источник
1

Мне очень нравится сортировать ключи в одном коде строки:

print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
labist
источник