Як я можу надрукувати вміст хеша в Perl?


167

Я продовжую друкувати свій хеш як # відра / # виділено. Як надрукувати вміст мого хеша?

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

Відповіді:


253

Дані :: Дампер - твій друг.

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

виведе

$VAR1 = {
          'def' => [
                     4,
                     5,
                     6
                   ],
          'abc' => 123
        };

3
оригінальний плакат може також захотіти вивчити різні параметри Data :: Dumper, зокрема включення "Sortkeys" може бути дуже корисним
plusplus

1
@JonathanDay Мені не вистачало цієї деталі, і це було корисно! Дякую!
Sos

5
Що означає додавання косої риски перед%?
шампунь

16
Оператор @shampoo слэш створює посилання, схоже на &оператора в 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
Sleazy: друкуйте "@_ \ 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%?
Карлос Са


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"
    }
}

мати кольори "акуратно", але я роблю щось не так, або використовую "використовувати Data :: Printer; p% var;" не друкує стрілки в хешах, а для такого новачка, як я, це допомагає
Sos

@Sosi Якщо ви подивитесь на результат у відповіді, то побачите, що він не виводить так, =>як ви очікували. Натомість він завжди друкує ключ, кілька пробілів, а потім значення. Що допомагає скануванню людини на вихід.
Бред Гілберт

12

Відповідь залежить від того, що є у вашому хеші. Якщо у вас простий хеш, простий

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

або

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

буде, але якщо у вас є хеш, заповнений посиланнями, ви зможете пройти ці посилання і отримати розумний результат. Таке посилання на посилання зазвичай називається серіалізацією. Існує багато модулів, що реалізують різні стилі, деякі з найбільш популярних:

Через те, що Data::Dumperє частиною основної бібліотеки Perl, вона, мабуть, є найпопулярнішою; проте деякі інші модулі можуть запропонувати дуже хороші речі.


10

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

use Smart::Comments;
# ...

### %hash

Це воно.


5
Вибачте, голосувати від мене за речі, які викрадають коментарі за фактичну функціональність. Програміст з технічного обслуговування може провести цілий день, намагаючись розібратися, чому такий код роздруковував несподівані речі.
MikeKulls

2
@MikeKulls, np. Це джерельний фільтр, тому я розумію. Крім того, написавши сценарії, які перевіряють кожен модуль, який я вклав у виробничу підготовку, що він не робить 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. Для власного коду я вибрав би свій передчуття. Або використання Dumper від tetro.


3
Немає функціональної різниці між вашими способами використання foreachта map. mapслід використовувати для перетворень списку, а не в недійсному контексті для імітації for-loop
friedo

було б цікаво побачити результати "байт-коду" кожного ... Цікаво, чи карта більш-менш ефективна.
Ape-inago

2

Найпростіший спосіб з мого досвіду - просто використовувати Dumpvalue .

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

Працює як шарм, і вам не доведеться турбуватися про форматування хеша, оскільки він виводить його так, як це робить налагоджувач Perl (відмінно підходить для налагодження). Крім того, Dumpvalue входить в комплект запасних модулів Perl, тому вам не доведеться возитися з CPAN, якщо ви стоїте за якимсь драконовим проксі (як я на роботі).


1

Якщо ви хочете бути педантичним і тримати його в одному рядку (без заяв про використання та шебанг), то я відправлю скарбничку від відповіді тетроміно і запропоную:

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

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


ОП каже, що у нього є "мій хеш", який потребує друку. Ця відповідь - це просто розум заради себе
якраз

ОП сподівалася зробити це в один рядок. Тільки показував однолінійний спосіб це робити. Отже, це гідно голосування?
Кайл Уолш

1

Я додаю один пробіл для кожного елемента хешу, щоб добре його побачити:

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

1

Мені дуже подобається сортувати ключі в одному вкладиші:

print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.