【发布时间】:2011-11-25 21:04:58
【问题描述】:
我正在尝试实现一个带有标题的多维表。
这是 2D 的示例:
< dimension1 >
/\ 'column0' 'column1'
dimension0 'row0' data00 data10
\/ 'row1' data01 data11
行和列的标题是文本,数据是任何东西。我希望能够做这样的事情(语法可以不同,我是 Perl 的初学者):
my $table = new table(2); # 2 is the number of dimensions
# the following line creates a new row/column if it didn't exist previously
$table['row0']['column0'] = data00;
$table['row0']['column1'] = data01;
$table['row1']['column0'] = data10;
$table['row1']['column1'] = data11;
# the following line returns the headers of the specified dimension
$table->headers(0);
=> ('row0', 'row1')
第一个问题:在 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];
}
【问题讨论】:
-
如果您的数据是由数字组成的,您可能会发现Math::MatrixReal 非常有用。
-
@MarcoDeLellis 这只是 2D,没有任何维度,也没有标题,所以很遗憾这不是我想要的。
-
我喜欢这个主意,今晚会尝试一下。
-
@JanHartung 太好了,如果您找到更好的方法,请告诉我。我已经在一个应用程序中实现了这个示例,经过一些分析后,我发现
header函数花费了太多时间。 -
@GiovanniFunchal:好的,您的代码似乎做得很好。当然可以进行一些调整,但为此我想了解更多信息。您分析了代码,所以我猜性能是一个问题。当我使用我的测试用例(大致是您的示例使用场景)进行分析时,
data函数花费了大约 60% 的时间。最好的事情是如果您可以提供一些示例数据和您想要使用它执行的实际操作的描述。同样有趣的是你对内存的慷慨,所以也许我们可以通过使用散列而不是数组来加快速度。
标签: perl cpan perl-module perl-data-structures perl-hash