在Perl中存储1key - 3值的最佳方法是什么?

时间:2012-04-23 16:31:40

标签: perl hash

我的情况是每个键有3个不同的值。我必须打印这样的数据:

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

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

  1. 为每个键保留3个不同值的3个哈希值。 根据键迭代一个哈希值,并从其他2个哈希值中获取值 并打印出来。

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

    K1 --> Ref{V1,V2,V3}
  3. EDIT1:

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

    例如,我在子程序1中 - 我填充了Hash1 - K1-->[V1] 我在子程序2中 - 我必须取消引用[V1],然后按V2。哈哈,现在哈希 变为K1-->[V1 V2]V3被添加到另一个例程中。 K1-->[V1 V2 V3]

    EDIT2:

    现在我面临着另一个挑战。我必须根据V3对哈希进行排序。 使用键和列表引用存储哈希是否可行?

    K1-->[V1 V2 V3]

5 个答案:

答案 0 :(得分:9)

这实际上取决于你想对数据做些什么,虽然我无法想象你的选择1对任何事情都很方便。

如果您喜欢使用索引0,1,2或者您真的不想单独处理其值,请使用数组哈希值V1V2V3

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

答案 1 :(得分:1)

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

  1. 根据我的经验,更为常见,
  2. 易于维护,因为您只有一个数据结构而不是三个,而且
  3. 更符合the DRY principle:“每一条知识都必须在系统中具有单一,明确,权威的表现形式。”代表一次密钥,而不是三次。

答案 2 :(得分:1)

在可读性/可维护性方面,第二个似乎优于我。第一个问题的危险在于你最终可能会将密钥存在于一个哈希中而不是其他哈希中。另外,如果我遇到第一种方法,我必须考虑它一段时间,而第一种似乎是“自然的”(或更常见的习语,或更实际,或其他意味着我理解它更容易)。

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

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

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

第二种方法与面向对象的编程紧密结合。面向对象编程是Perl中最常见的编程风格,因此第二种方法几乎普遍是目前最受欢迎的结构(即使需要更多内存)。

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

最适合您代码组织的任何内容。