嵌套的 perl 数组和散列和引用
Nested perl arrays and hashes and references
我已经尝试了@%$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 头脑”:(。非常感谢任何帮助。
语法 %cols[1]
是一个 index-value array slice。如果 @cols
只有一个元素,则索引 1 处的值未定义,并且 %cols[1]
returns 列表 (1, undef)
在第 4 行分配给 %col
你的第一个片段:
my %col = %cols[1];
所以现在 %col = ("1" => undef)
当您尝试在第 5 行打印它时:
print "COLvar ", %col, " ", "\n";
它尝试打印与值 undef
连接的键“1”,它发出警告,然后输出:
Use of uninitialized value in print
COLvar 1
以下示例演示代码提供了多种可能的方法之一来形成 OP 命名为数据库 shema.
函数 addColumn($name, $type)
中的 OP 没有指定 table 列属于什么。
很高兴看到 OP 期望构建 的最终数据结构,以阐明最终结果。
提供示例代码,希望它能帮助 OP 找到 his/her 问题的解决方案。
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 中对 object oriented programming 做一些阅读,这将允许将 table data/structure 封装到一个对象中。结果代码看起来更清晰,更易于维护。
伪代码示例
......
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');
.....
您可以使用模块 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';
如您所见,您实际上有一个嵌套数组。所以你需要先访问嵌套数组,然后再访问散列。
感谢您的帖子,但其中 none 解决了实际问题。解决方案是
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} 是取消引用运算符。
我还是不太明白“%”等到底是干什么的。我怀疑最好只使用引用并完全避免使用 % 和 @。
这个 link 非常有帮助
https://perldoc.perl.org/perlreftut
我已经尝试了@%$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 头脑”:(。非常感谢任何帮助。
语法 %cols[1]
是一个 index-value array slice。如果 @cols
只有一个元素,则索引 1 处的值未定义,并且 %cols[1]
returns 列表 (1, undef)
在第 4 行分配给 %col
你的第一个片段:
my %col = %cols[1];
所以现在 %col = ("1" => undef)
当您尝试在第 5 行打印它时:
print "COLvar ", %col, " ", "\n";
它尝试打印与值 undef
连接的键“1”,它发出警告,然后输出:
Use of uninitialized value in print
COLvar 1
以下示例演示代码提供了多种可能的方法之一来形成 OP 命名为数据库 shema.
函数 addColumn($name, $type)
中的 OP 没有指定 table 列属于什么。
很高兴看到 OP 期望构建 的最终数据结构,以阐明最终结果。
提供示例代码,希望它能帮助 OP 找到 his/her 问题的解决方案。
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 中对 object oriented programming 做一些阅读,这将允许将 table data/structure 封装到一个对象中。结果代码看起来更清晰,更易于维护。
伪代码示例
......
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');
.....
您可以使用模块 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';
如您所见,您实际上有一个嵌套数组。所以你需要先访问嵌套数组,然后再访问散列。
感谢您的帖子,但其中 none 解决了实际问题。解决方案是
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} 是取消引用运算符。
我还是不太明白“%”等到底是干什么的。我怀疑最好只使用引用并完全避免使用 % 和 @。
这个 link 非常有帮助 https://perldoc.perl.org/perlreftut