#perl
Вопрос:
Я пробовал различные комбинации @%$s, но не могу заставить это работать. Полное выражение работает, но как мне разделить его на переменные?
print "BIGexp ", $tables{"grp"}[1]{_name}, "n"; # OK, prints part
my @cols = $tables{"grp"};
print "COLS ", @cols, "n"; # prints array
my %col = %cols[1];
print "COLvar ", %col, " ", "n"; #prints 1 ?
print "COLexp ", $cols[1]{_name}, "n"; ######## Fails, uninitialized.
Я хочу представить схемы баз данных. Итак, карта таблиц, каждая из которых содержит массив столбцов, каждый из которых является картой. Вот полный фрагмент.
my %tables=();
my $columns; # array
sub addTable {
my @cols = ();
$tables{$_[0]} = @cols;
$columns = @cols;
}
sub addColumn {
my %col = (_name => $_[0], _typ => $_[1]);
push(@$columns , %col);
}
addTable("grp");
addColumn("id", "serial");
addColumn("part", "integer");
addTable("tab2");
addColumn("foo2", "varchar");
addColumn("bar2", "integer");
print "BIGexp ", $tables{"grp"}[1]{_name}, "n"; # OK, prints part
my @cols = $tables{"grp"};
print "COLS ", @cols, "n"; # prints array
my %col = %cols[1];
print "COLvar ", %col, " ", "n"; #prints 1 ?
print "COLexp ", $cols[1]{_name}, "n"; ######## Fails, uninitialized.
Я новичок в Perl и еще не стал «настроенным на Perl» :(. Любая помощь очень ценится.
Комментарии:
1. Быстрое (но необходимое) чтение, чтобы начать работу со ссылками: perldoc.perl.org/perlreftut
2. «мой %col = %cols[1];» : Попробуйте
my %col = %{$cols->[1]}
3. «Я пробовал различные комбинации @%$s». Мне больше всего нравится в этом вопросе то, что похоже, что вы подвергаете цензуре ругательство, но вы просто точно описываете синтаксис Perl.
4. @Данные да, эта ссылка очень хороша и дала мне ответ. Спасибо.
Ответ №1:
Вы можете использовать модуль use Data::Dumper;
для печати ваших структур данных.
print "BIGexp ", $tables{"grp"}[1]{_name}, "n"; # OK, prints part
my @cols = $tables{"grp"};
print "COLS ", @cols, "n"; # prints array
my %col = %cols[1];
print "COLvar ", Dumper(%col), " ", "n"; #prints 1 ?
print "COLexp ", Dumper(@cols), "n"; ######## Fails, uninitialized.
print "COLexp ", Dumper($cols[0][1]{_name}), "n";
И результат такой:
BIGexp part
COLS ARRAY(0x800e5f480)
COLvar $VAR1 = {
'1' => undef
};
COLexp $VAR1 = [
[
{
'_typ' => 'serial',
'_name' => 'id'
},
{
'_name' => 'part',
'_typ' => 'integer'
}
]
];
COLexp $VAR1 = 'part';
Как вы можете видеть, на самом деле у вас есть вложенный массив. Поэтому вам нужно сначала получить доступ к вложенному массиву, а затем к хэшу.
Комментарии:
1. А? Как он стал вложенным? И какое заклинание требуется, чтобы его отменить? [0] не помогает. И что именно такое $%@.. Это своего рода просто синтаксический шум, но также и своего рода операторы, которые меняют семантику. Я называю их «перлами». Спасибо, но
2. Он становится вложенным здесь :
my @cols = $tables{"grp"};
в основном вы создаете новый массив и внутри него добавляете свой массив из хэша %таблиц. Вы можете увидеть это с помощью:print "Inside tables", Dumper($tables{"grp"}),"n";
теперь есть только один массив с хэшами.3. Вы можете отменить его, выполнив:
my @arr = map {$_->[0]} @cols; print Dumper(@arr);
это выведет первый элемент массива, который является тем массивом, который вам нужен.
Ответ №2:
Следующий пример демонстрационного кода предоставляет один из многих возможных способов формирования того, что ОП назвал базой данных shema.
Функция OP in addColumn($name, $type)
не указывает, к какой таблице принадлежит столбец.
Было бы неплохо посмотреть, какую окончательную структуру данных OP ожидает построить, чтобы уточнить, каким будет конечный результат.
Пример кода предоставлен в надежде, что он может помочь оператору в поиске решения его/ее проблемы.
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my %tables;
tbAddColumn('grp','id','serial');
tbAddColumn('grp','part','integer');
tbAddColumn('tab2','foo2','varchar');
tbAddColumn('tab2','bar2','integer');
say Dumper(%tables);
my $tb_name = 'grp';
say "Table: $tb_name";
say '-' x 45;
for my $column ( @{$tables{$tb_name}{columns}} ) {
say "name => $column->{name}, type => $column->{type}";
}
exit 0;
sub tbAddColumn {
my $tbname = shift;
my $name = shift;
my $type = shift;
push @{$tables{$tbname}{columns}}, { name => $name, type => $type};
}
Выход
$VAR1 = {
'tab2' => {
'columns' => [
{
'name' => 'foo2',
'type' => 'varchar'
},
{
'name' => 'bar2',
'type' => 'integer'
}
]
},
'grp' => {
'columns' => [
{
'name' => 'id',
'type' => 'serial'
},
{
'type' => 'integer',
'name' => 'part'
}
]
}
};
Table: grp
---------------------------------------------
name => id, type => serial
name => part, type => integer
ПРИМЕЧАНИЕ: OP мог бы немного почитать об объектно-ориентированном программировании на Perl, которое позволило бы инкапсулировать табличные данные/структуру в объект. Код результата будет выглядеть намного чище и проще в обслуживании.
Образец псевдокода
......
my $tb1 = new dbTable('grp');
my $tb2 = new dbTable('tab2');
$tb1->addColumn('id','serial');
$tb1->addColumn('part','integer');
$tb2->addColumn('foo2','varchar');
$tb2->addColumn('bar2','integer');
.....
Комментарии:
1. OP использовал глобальную переменную для хранения текущей таблицы ($columns), чтобы сделать вызовы немного более краткими, и, похоже, она создает правильную структуру в соответствии с Dumper. Мог бы использовать другой стиль. Но вы не отвечаете на мой вопрос, а именно, как мне индексировать созданную структуру. (Я также не понимаю вашего причудливого толчка, но вопрос не в этом.)
2. Вы обращаетесь к структуре следующим образом
$tables{$tbname}{columns}[$index]{$key}
(или вы можете использовать$tables{'grp'}{'columns'}[0]{'name'}
, например, если ключ состоит из одного слова, то кавычки могут быть опущены).$tables{$tbname}{columns}
является arrayref , вы не можете вставить элемент в arrayref , он требует разыменования@{$arrayref}
.3. @Tuntable Я отредактировал ваш вопрос с добавлением, демонстрирующим доступ к сохраненным данным, хотя и создал копию массива/хэша в соответствии с вашим примером кода (в данном конкретном случае это не нужно, так как копирование требует циклов памяти и процессора). Если вам не нужны дубликаты данных, то доступ может быть обеспечен с помощью ссылки на массив/хэш-это намного быстрее, не потребляет память и экономит циклы процессора .
4. @PolarBear Я откатил вашу правку по этому вопросу. Код, который вы добавили, пришел без объяснений, и текст содержался в ответе, а не в вопросе. Помните, что вы можете опубликовать несколько ответов, если захотите.
5. @Dada — это, если меня устраивает, меня больше не волнует этот вопрос.
Ответ №3:
Синтаксис %cols[1]
представляет собой срез массива значений индекса. Если @cols
есть только один элемент, значение индекса 1 не определено и %cols[1]
возвращает список (1, undef)
, которому присвоена %col
строка 4 в вашем первом фрагменте:
my %col = %cols[1];
Итак, сейчас %col = ("1" => undef)
и когда вы пытаетесь распечатать его в строке 5:
print "COLvar ", %col, " ", "n";
Он пытается напечатать ключ «1», соединенный со значением undef
, которое выдает предупреждение, а затем вывод:
Use of uninitialized value in print
COLvar 1
Комментарии:
1. А? $cols[1] не работает. Так как же можно не делать срез и не делать простой индекс?
2. @Tuntable В данном случае
$#cols == 0
так$cols[1]
не существует. Я не уверен, что вы подразумеваете под «не работает» . Пожалуйста, уточните
Ответ №4:
Спасибо за сообщения, но ни одно из них не решило реальную проблему. Решение заключается в следующем
print "BIGexp ", $tables{"grp"}[1]{_name}, "n"; # OK, part
my $cols = $tables{"grp"}; # ref array
my $col = ${$cols}[1]; # ref hash
my %colh = %{$col}; # hash
print "COLvar ", $colh{_name}, " ", "n"; # bingo
print "COLvar2 ", ${$col}{_name}, " ", "n"; # bingo
print "COL-> ", $col->{_name}, " ", "n"; # bingo
Хитрость заключается в том, чтобы позаботиться о разнице между массивом ссылок и массивом и т. Д. {$x} — оператор разыменования.
Я все еще не совсем понимаю, что на самом деле делает «%» и т. Д. Я подозреваю, что лучше всего использовать только ссылки и полностью избегать % и @.
Эта ссылка была очень полезной https://perldoc.perl.org/perlreftut
Комментарии:
1. Прежде чем перейти к этому представлению, пожалуйста, ознакомьтесь также с другим разделом документов Perl, а именно с разделом о переменных Perl: perldoc.perl.org/perlvar .