2

我有一种情况,每个键都有 3 个不同的值。我必须像这样打印数据:

K1 V1 V2 V3
K2 V1 V2 V3
…
Kn V1 V2 V3

是否有任何替代的有效和更简单的方法来实现下面列出的其他方法?我正在考虑两种方法:

  1. 为每个键维护 3 个不同值的 3 个哈希值。根据键迭代一个哈希并从其他 2 个哈希中获取值并打印它。

    哈希 1 - K1-->V1 ...
    哈希 2 - K1-->V2 ...
    哈希 3 - K1--> V3 ...
  2. 使用键来维护单个哈希以引用值数组。在这里,我需要迭代并只读取 1 个哈希。

    K1 --> 参考{V1,V2,V3}

编辑1:

主要的挑战是,V1、V2、V3 的值是在不同的地方导出的,不能作为数组推到一起。因此,如果我将哈希值作为对数组的引用,则每次我想添加下一个值时都必须取消引用它。

例如,我在 subroutine1 - 我填充了 Hash1 -K1-->[V1] 我在 subroutine2 - 我必须取消引用[V1],然后 push V2。所以现在哈希变成K1-->[V1 V2],V3被添加到另一个例程中。K1-->[V1 V2 V3]

编辑2:

现在我面临另一个挑战。我必须根据V3. 用键和列表引用存储散列仍然可行吗?

K1-->[V1 V2 V3]

4

5 回答 5

9

这实际上取决于您想对数据做什么,尽管我无法想象您的选项 1 对任何事情都很方便。

如果您乐于使用索引 0、1、2引用您的V1, V2,或者如果您真的不想单独处理它们的值,请使用数组哈希。V3

my %data;
$data{K1}[0] = V1;
$data{K1}[1] = V2;
$data{K1}[2] = V3;

或者,当然

$data{K1} = [V1, V2, V3];

作为一个附加选项,如果您的值意味着可命名的东西,您可以使用哈希哈希,所以

my %data;
$data{K1}{name} = V1;
$data{K1}{age} = V2;
$data{K1}{height} = V3;

或者

$data{K1}{qw/ name age height /} = (V1, V2, V3);

最后,如果您永远不需要访问单个值,则可以将它们保留在文件中,就像这样

my %data;
$data{K1} = "V1 V2 V3";

但正如我所说,内部存储主要取决于您希望如何访问数据,而您还没有告诉我们这一点。


编辑

既然你说

主要挑战是,V1、V2、V3 的值是在不同的地方导出的,不能作为数组推到一起

我认为散列的散列可能更合适,但我一点也不担心取消引用,因为就执行时间而言,它是一个微不足道的操作。但我不会使用push它,因为这会限制您以正确的顺序添加数据。

根据您的喜好,您可以选择

$data{K1}[2] = V3;

或者

$data{K1}{height} = V3;

显然后者更具可读性。


编辑 2

根据要求,要按第三个值(在我的示例中)对哈希值进行排序,height您可以编写

use strict;
use warnings;

my %data = (
  K1 => { name => 'ABC', age => 99, height => 64 },
  K2 => { name => 'DEF', age => 12, height => 32 },
  K3 => { name => 'GHI', age => 56, height => 9 },
);

for (sort { $data{$a}{height} <=> $data{$b}{height} } keys %data) {
  printf "%s => %s %s %s\n", $_, @{$data{$_}}{qw/ name age height / };
}

或者,如果数据存储为数组的散列

use strict;
use warnings;

my %data = (
  K1 => [ 'ABC', 99, 64 ],
  K2 => [ 'DEF', 12, 32 ],
  K3 => [ 'GHI', 56, 9 ],
);

for (sort { $data{$a}[2] <=> $data{$b}[2] } keys %data) {
  printf "%s => %s %s %s\n", $_, @{$data{$_}};
}

两个脚本的输出是相同的

K3 => GHI 56 9
K2 => DEF 12 32
K1 => ABC 99 64
于 2012-04-23T17:23:29.293 回答
1

第二种方法(每个键的一个数组引用)是:

  1. 根据我的经验,更常见的是,
  2. 更易于维护,因为您只有一个数据结构而不是三个浮动,并且
  3. 更符合DRY 原则:“每一条知识都必须在系统中具有单一的、明确的、权威的表示。” 代表一个键一次,而不是三次。
于 2012-04-23T16:48:20.803 回答
1

在可读性/可维护性方面,第二个似乎优于我。第一个的危险是您最终可能会在一个散列中出现键,但在其他散列中不存在。另外,如果我遇到第一种方法,我将不得不考虑一段时间,而第一种似乎“自然”(或更常见的习语,或更实用,或者其他意味着我会理解它的东西更容易)。

于 2012-04-23T16:51:10.547 回答
0

当然,最好只维护一种数据结构:

%data = ( K1=>[V1, V2, V3], ... );

您可以使用Data::Dump快速查看/调试数据结构。

于 2012-04-23T16:48:29.217 回答
0

选择实际上取决于使用模式。具体来说,这取决于您使用的是过程程序还是面向对象的编程。

这是哲学上的差异,与是否使用语言级别的类和对象无关。程序性编程是围绕工作流程组织的;过程访问和转换它需要的任何数据。OOP 是围绕数据记录组织的;方法只访问和转换一个特定的记录。

第二种方法与面向对象编程密切相关。面向对象编程是迄今为止 Perl 中最常见的编程风格,因此第二种方法现在几乎是普遍首选的结构(尽管它需要更多内存)。

但是您的编辑暗示您可能正在使用更多的程序方法。正如您所发现的,第一种方法对于过程式编程更方便。当过程式编程流行时,它非常常用。

采用最适合您的代码组织的方式。

于 2012-04-23T17:38:59.770 回答