【问题标题】:What is the best way to store 1key - 3 value in Perl?在 Perl 中存储 1key - 3 值的最佳方法是什么?
【发布时间】:2012-05-04 07:09:59
【问题描述】:

我有一种情况,每个键都有 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],然后推送 V2。所以现在哈希 变为K1-->[V1 V2]V3 被添加到另一个例程中。 K1-->[V1 V2 V3]

编辑2:

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

K1-->[V1 V2 V3]

【问题讨论】:

    标签: perl hash


    【解决方案1】:

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

    1. 根据我的经验,这种情况更为常见,
    2. 更易于维护,因为您只有一个浮动数据结构而不是三个,并且
    3. 更符合the DRY principle 的说法:“每条知识在系统中都必须有一个单一的、明确的、权威的表示。”代表一个键一次,而不是三次。

    【讨论】:

    • 与言外之意相反,第一种方法并没有使(3)中引用的DRY原则失效。
    • 怎么样?每个键在三个不同的哈希中表示三次。
    • 有几种解释方式,但举个例子最简单:你自己的链接显示DRY适用于关系型数据库,第一种方式无非是关系型数据库的最低要求。
    • 好吧,在这种情况下,“键”不再是键(在主键的意义上——或者,更具体地说,具有unique 约束的列)。
    • @Borodin,与任何其他关系数据库(例如 PostgreSQL 表)相同。这是因为 id 不是“知识”,关系本身是。即使相同的 id 存储在三个位置,关系仍然使用“单一的、明确的、权威的表示”来存储。
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        这真的取决于你想对你的数据做什么,虽然我无法想象你的选项 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,我喜欢你关于哈希的想法。你能举例说明我如何根据第三个值进行排序,比如V3?请看我的 EDIT2
        • @cppcoder:我已添加到我的答案中,以演示如何对哈希哈希和数组哈希进行排序。
        【解决方案5】:

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

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

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

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

        选择最适合你的代码组织的东西。

        【讨论】:

        • PS - 如果“我每次想添加下一个值时都必须取消引用它。”
        • 它让我多写几行代码,让代码变得复杂。
        • @cppcoder, while (...) { push @{ $x[++$i] }, get_val(); } 的行数不超过while (...) { push @y, get_val(); }。复杂性略有增加,稍后当您尝试访问数据时,可能会相应降低复杂性。
        • @ikegami-现在我有另一个挑战。请参阅 EDIT2
        • @cppcode, 1) 没有对列表的引用。您正在谈论对数组的引用。 2)哈希无法排序。您可以对其键进行排序,是的,它们可以基于 V3 进行排序。 my @sorted_keys = sort { $a-&gt;[2] cmp $b-&gt;[2] } keys(%hash);
        猜你喜欢
        • 2012-10-23
        • 2017-02-22
        • 2013-02-15
        • 2010-12-16
        • 2013-05-23
        • 2011-02-27
        • 2011-06-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多