PERL - статьи

       

Хэши slice


(перевод, статья находится по адресу )

Насколько хорошим является этот код??

@array = qw( a b c d ) ;

@array{ @array } = ( [ @array ] ) x @array ;

Основное определение хэша slice: @hash{ @array } = ( list ) что эквивалентно ( $hash{ $array[0] }, ... $hash{ $array[$#array] } ) = ( list ) Префиксный символ (@ ,%) используется только для обозначения контекста, но не типа данных. Если имеются два массива и мы ходим сопоставлять их данные, то мы поступаем так:

@foo_array = qw( abc def ghi ) ;

@bar_array = qw( jkl mno pqr ) ;

@foo_to_bar{ @foo_array } = @bar_array

теперь можно работать с массивами немного проще:

$foo_value = 'def' ;

$bar_value = $foo_to_bar{ $foo_value } ;

Можно даже сразу преобразовывать целый массив переменных foo одной конструкцией: @bar_values = @foo_to_bar{ @foo_values }; Еще одно использование хэша slice, производится проверка: находится ли строка в данном массиве строк? Фактически мы не заботимся о том, что находится в хеше slice, но 1 используется для большей ясности.

@foo_array = qw( abc def ghi ) ;



@is_a_foo{ @foo_array } = (1) x @foo_array ;

$input = 'def' ;

if ( $is_a_foo{ $input } ) {

...

if ( exists( $is_a_foo{ $input } ) ) {

...

Оператор x называется оператором повторения, он дублирует левый операнд значением правого операнда. В скалярном контексте он копирует левый оперант как строку и возвращает его, т.е. мы имеем контекст списка и левый операнд списка. Это позволяет создать новый список с N копиями предыдущего списка. Для foo N = 3 и (скалярное значение @foo_array) и мы получаем список (1, 1, 1) который присваивается хешу slice. Программа, преобразующая строки в нумерованные индексные значения. Используется оператор диапазона (..), создающий список целых чисел, которые присваиваются хэшу slise:

@foo_array = qw( abc def ghi ) ;

@foo_to_index{ @foo_array } = ( 0 .. $#foo_array ) ;

@foo_to_index{ @foo_array } = ( 1 .. @foo_array ) ;

$i_am_a_foo = 'def' ;

$foo_index = $foo_to_index{ $i_am_a_foo } ;

Названия %foo_to_bar, %is_a_foo, $foo_to_index подобраны так, чтобы нагляднее показать принцип работы slise. Фактически была проведена индексация входных данных и выходных данных в хеш splice. Теперь рассмотрим хэш splice снова @array{ @array } = ( [ @array ] ) x @array ;. Заметим, что хэш и массив(и скаляр) называются массивами, но это различные переменные, в частности отличные по разделитеям. Левая часть выражения - присваивание хэшу slice, но что-же стоит справа? Оператор x и @array справа дублирует повторения счетчика и некоторый лист слева и мы имеем контекстный список. Хеш slice есть список контекстов, мы создаем скопированный список анонимного массива, который содержит значения в @array. Это значит что хэш %array напоминает такой массив:


%array = (

'a' => [ 'a', 'b', 'c', 'd' ],

'b' => [ 'a', 'b', 'c', 'd' ],

'c' => [ 'a', 'b', 'c', 'd' ],

'd' => [ 'a', 'b', 'c', 'd' ],

) ;

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

@foo_list = qw( a b c d );

@bar_list = qw( j k l m n o );

@baz_list = qw( w x );

@expand_aliases{ @foo_list } = ( [ @foo_list ] ) x @foo_list;

@expand_aliases{ @bar_list } = ( [ @bar_list ] ) x @bar_list;

@expand_aliases{ @baz_list } = ( [ @baz_list ] ) x @baz_list;

Если есть лексемма неопределенного типа, то можно получить список псевдонимов за 1 шаг @aliases = @{ $expand_aliases{ $alias } } ; Окружение @{} используется, чтобы разыменовать сохраненный анонимный список в список для присвоения @aliases.

есть хэш, типа

$myhash{name}=qwert;

$myhash{age}=15;

как сделать автоматическое создание переменной=ключу хэша со значением

из этого хэша с этим же ключом, т.е. $name=qwert; $age=15 и т.д.

либо так:

my %myhash;

$myhash{name}='qwert';

$myhash{age}=15;

for $abc (keys %myhash)

{

$$abc=$myhash{$abc};

}

print "\$name=$name; \$age=$age\n и т.д.";

либо так:

$$_ = $myhash{$_} for keys %myhash;

что в принципе одно и то-же...

from:

Объявление анонимного хеша:

Ссылки на существующие данные часто применяются для передачи аргументов функции, но в динамическом программировании они бывают неудобны. Для любой переменной

есть два параметра, е имя и адрес области памяти, где хранится эта переменная. Скалярная величина, хранящая адрес области памяти, назвается ссылкой. Значение, хранящееся в памяти по данному адресу называется субъектом(referent).

Анонимные хеши в perl могут создаваться явно. При этом выделяется память для хеша и возвращается ссылка на не .

$hash{map{$_ => $_*$_}(0 .. 4)}

while(($k, $v) = each %$hash){

print "$k => $v\n";

}

print $hash->{"3"}, "\n";

в цикле использовалась ссылка $hash на анонимный хеш.

Обратиться к нужному элементу хеша можно и при помощи ассоциативного оператора стрелка ->:

print $hash->{"3"}, "\n";

Пример использования анонимного хеша для выкидывания повторяющихся элементов из массива:

keys %{{ map { $_, 1 } @array }} # @array -> anonymous hash -> keys

Источник:


Содержание раздела