Perl多维表的标题
我正在尝试实现一个带有标题的多维表 以下是2D的一个示例:Perl多维表的标题,perl,cpan,perl-module,perl-data-structures,perl-hash,Perl,Cpan,Perl Module,Perl Data Structures,Perl Hash,我正在尝试实现一个带有标题的多维表 以下是2D的一个示例: < dimension1 > /\ 'column0' 'column1' dimension0 'row0' data00 data10 \/ 'row1' data01 data11 第一个问题:在CPAN中是否已经做过类似的事情?(在你问之前,我确实花了很长时间搜索,但没有找到类似的东
< dimension1 >
/\ 'column0' 'column1'
dimension0 'row0' data00 data10
\/ 'row1' data01 data11
第一个问题:在CPAN中是否已经做过类似的事情?(在你问之前,我确实花了很长时间搜索,但没有找到类似的东西)
第二个问题:这是我的尝试,我知道这很难看,可能是错的。有没有Perl专家愿意查看我的代码
package table;
sub new {
my $class = shift;
my $dimensions = shift;
my $self = bless({}, $class);
$self->{dimensions} = $dimensions;
$self->{data} = [];
$self->{headers} = [];
return $self;
}
sub get_dimensions {
my $self = shift;
return $self->{dimensions};
}
# This function creates a header or return its index if it already existed.
# Headers are encoded as an array of hashes so that this is O(1) amortized.
sub header {
my $self = shift;
my $dimension = shift;
my $header = shift;
my $headers = $self->{headers}[$dimension];
if(!defined($headers)) {
$headers = $self->{headers}[$dimension] = {};
}
if(!defined($headers->{$header})) {
$headers->{$header} = scalar keys %$headers;
}
return $headers->{$header};
}
# This function returns the list of headers. Because the headers are
# stored as a hash (`header=>index`), I need to retrieve the keys
# and sort them by value.
sub get_headers {
my $self = shift;
my $dimension = shift;
my $headers = $self->{headers}[$dimension];
return [sort { $headers->{$a} cmp $headers->{$b} } keys %$headers];
}
# This last function stores/retrieves data from the table.
sub data {
my $self = shift;
my $data = $self->{data};
my $dimensions = $self->{dimensions};
for(my $i = 0; $i < $dimensions-1; ++$i) {
my $index = $self->header($i, shift);
if(!defined($data->[$index])) {
$data->[$index] = [];
}
$data = $data->[$index];
}
my $index = $self->header($dimensions-1, shift);
my $value = shift;
if(defined($value)) {
$data->[$index] = $value;
}
return $data->[$index];
}
包表;
次新{
我的$class=shift;
我的$dimensions=shift;
我的$self=祝福({},$class);
$self->{dimensions}=$dimensions;
$self->{data}=[];
$self->{headers}=[];
返回$self;
}
子维{
我的$self=shift;
返回$self->{dimensions};
}
#此函数用于创建标题或返回其索引(如果已存在)。
#标头被编码为哈希数组,因此这是O(1)摊销的。
副标题{
我的$self=shift;
我的$dimension=shift;
我的$header=shift;
my$headers=$self->{headers}[$dimension];
如果(!已定义($headers)){
$headers=$self->{headers}[$dimension]={};
}
如果(!已定义($headers->{$header})){
$headers->{$header}=标量键%$headers;
}
返回$headers->{$header};
}
#此函数用于返回标题列表。因为标题是
#存储为散列(`header=>index`),我需要检索键
#并按值对它们进行排序。
子标题{
我的$self=shift;
我的$dimension=shift;
my$headers=$self->{headers}[$dimension];
返回[sort{$headers->{$a}cmp$headers->{$b}}键%$headers];
}
#最后一个函数用于存储/检索表中的数据。
子数据{
我的$self=shift;
my$data=$self->{data};
my$dimensions=$self->{dimensions};
对于(我的$i=0;$i<$dimensions-1;++$i){
我的$index=$self->header($i,shift);
如果(!已定义($data->[$index])){
$data->[$index]=[];
}
$data=$data->[$index];
}
my$index=$self->header($dimensions-1,shift);
我的$value=shift;
如果(定义的($value)){
$data->[$index]=$value;
}
返回$data->[$index];
}
您可以使用。这是我用你的例子做的一个快速试验
use strict;
use warnings;
use Text::TabularDisplay;
my $t = Text::TabularDisplay->new(('', 'column0', 'column1'));
$t->add('row0', 'data00', 'data10');
$t->add('row1', 'data01', 'data11');
print $t->render;
显示:
+------+---------+---------+
| | column0 | column1 |
+------+---------+---------+
| row0 | data00 | data10 |
| row1 | data01 | data11 |
+------+---------+---------+
我不确定这是否正是你想要的。您必须将第一列留空,从而篡改标题。在这里可能有用。我在下面展示一个简单的例子:您可以使用模块提供的各种选项来创建与您描述的内容相近的内容
#!/usr/bin/perl
use warnings;
use strict;
use Text::Table;
my $inner_table = Text::Table->new(qw(column0 column1));
$inner_table->load(
[ qw(row0 data00 data01) ],
[ qw(row1 data10 data11) ],
);
my $outer_table = Text::Table->new(' ', 'dimension1');
$outer_table->load(
['dimension0', $inner_table->stringify ],
);
print $outer_table;
输出
C:\Temp>t
尺寸1
尺寸0列0列1
第0行数据00
第1行数据10您需要“N”维表的结构。我怀疑是否有CPAN模块可以做到这一点,因为这种情况并不常见 问题是,数据结构增长非常快,复杂性也是如此 通过使用一些数学知识将N维数组转换为单个维度,可以将N维表存储在单个列表中。假设X代表X维,X'代表该维的长度。对于二维表格,您可以通过执行以下操作获得值:
X * Y` + Y.
对于三维表格X、Y、Z,答案是:
X * (Y' * Z') + Y * Z' + Z
W * (X' * Y' * Z') + X * (Y' + Z') + Y * Z' + Z'
对于四维表格W,X,Y,Z,答案是:
X * (Y' * Z') + Y * Z' + Z
W * (X' * Y' * Z') + X * (Y' + Z') + Y * Z' + Z'
(我希望数学是正确的)
因此,我可以想象这样一个N维表的结构。它将涉及两个不同的类:一个表示维度信息,另一个表示实际数据(包括所有维度)
- 维度(类)
- 标题(字母数字字符串)
- 维度大小(整数)
- N-表(类)
- 维度数组(维度类对象)
- 数据数组(字母数字字符串)
my $numOfDimensions = scalar @{$ntable->{DIMENSIONS}};
my xDimensionHeading = $ntable->{DIMENSION}->[$x]->{HEADING};
my xDimensionSize = $ntable->{DIMENSION}->[$x]->{SIZE};
并且,您可以通过查看以下内容获得维度$x
的标题:
my $numOfDimensions = scalar @{$ntable->{DIMENSIONS}};
my xDimensionHeading = $ntable->{DIMENSION}->[$x]->{HEADING};
my xDimensionSize = $ntable->{DIMENSION}->[$x]->{SIZE};
通过查看以下内容,可以确定该维度的大小:
my $numOfDimensions = scalar @{$ntable->{DIMENSIONS}};
my xDimensionHeading = $ntable->{DIMENSION}->[$x]->{HEADING};
my xDimensionSize = $ntable->{DIMENSION}->[$x]->{SIZE};
当然,您可以使用真正的面向对象调用来实现这一点,而不是直接引用,但这让您了解了该结构的工作原理
现在,您需要一种将表示单元格位置的整数列表转换为沿一维数组的单元格位置的方法,并且您将有一种获取和检索数据的方法
这就是你要找的吗
编辑
接近它,但我实际上调整了很多表维度的大小(我无法事先确定它们的大小),如果我理解您的解决方案不能适应这一点的话 这增加了很多复杂性 我们需要在维度类中去掉大小。而且,我们不能使用一维数组来存储数据 我希望你不要改变桌子的尺寸 我们可以这样做:
- N-表(类)
- 维度标题列表{Dimension}->[]
- 列表到数据{Data}->[](这可以是到其他列表的链接)
my data_3D = $table_3D->{DATA}->[$x]->[$y]->[$z];
my data_2D = $table_2D->{DATA}->[$x]->[$y];
维度的数量是scalar@{$table->{DIMENSION}
问题是我如何以维度中立的方式访问数据。我可能需要2个、3个、4个或更多维度,而且我必须有某种方式来构建我的地址才能将其拉出
我们可以有某种循环机制。我们得到@坐标中的坐标列表,然后查看每个坐标。最后一个将指向数据。其余的将只是对另一个数组的另一个引用
my $data = pop @coordinates; #First Coordinate
$data = $table->[$data]; #Could be data if 1D table, could be a reference
foreach my $coordinate (@coordinates) {
die qq(Not enough coordinates) if ref $data ne 'ARRAY';
$data = $data->[$coordinate]; #Could be data, could be a reference
}
# Cell value is in $data
也可以建立一个坐标列表,然后对其进行评估。再次完全未经测试:
$coordinates = "[" . join ("]->[" => @coordinates . "]";
如果有三个坐标,这就是
$coordinates = "[$x]->[$y]->[$z]";
我不确定一维数组如何工作
从那里,您可以构建一个语句并使用eval<