【问题标题】:How to find out if a Perl hash is multidimensional?如何确定 Perl 哈希是否是多维的?
【发布时间】:2010-08-26 06:36:01
【问题描述】:

假设我有这样的哈希:

$hash_ref = {

  'hashes' => {
    'h1' => { 'klf' => '1', 'moomooland' => '1' },
    'h2' => { 'klf' => '2', 'moomooland' => '2' },
    'h3' => { 'klf' => '3', 'moomooland' => '3' }
  },

  'keys' => {
    'k1' => 'key1',
    'k2' => 'key2',
    'k3' => 'key3'
  }

}

我怎样才能尽可能简单地找出 hashes 包含 3 个以上的哈希值,而 keys 包含 3 个键/值对?

ref 将为它们返回HASH,我不确定是否有可能找出这些散列的深度。

谢谢:)

【问题讨论】:

  • 是的,有可能,但我想知道你为什么想知道这个。这可能有助于确定合适的行动方案。例如你想返回最深的链,还是所有不同分支的深度?
  • 我需要知道这一点,以便我可以根据我得到 3 个哈希值还是 3 个键/值对来调用不同的操作。所以,如果我能以其他方式区分这两者,我不一定需要知道确切的深度。我现在看到您指向其他问题的链接,但我希望这可以在不使用递归的情况下完成:)
  • 这不是完全重复的,但是可以调整那里列出的方法来计算级别数。没有内置的方法可以做到这一点。
  • 我经常使用 Data::Dumper 来转储数据,但我不知道在这种情况下如何使用它。

标签: perl hash


【解决方案1】:

如果您只需要知道哈希是否是多维的,您可以遍历其值并在找到引用时停止:

my $is_multi_dimensional = 0;

for my $value (values %$hash_ref) {
    if ('HASH' eq ref $value) {
        $is_multi_dimensional = 1;
        last;
    }
}

或者你可以使用each()函数:

while (my (undef, $value) = each %$hash_ref) {
    if ('HASH' eq ref $value) {
        $is_multi_dimensional = 1;
        last;
    }
}

【讨论】:

  • 哦,这真是太棒了。如此简单,但又如此合乎逻辑和有效。唉,我怎么没想到呢? :) 谢谢尤金,这非常适合我的需要,尽管现在我意识到我的问题的措辞并没有真正解释这是我正在寻找的,而不是获得哈希的准确/实际深度。哎呀。
  • 你确定 each() 比 values() 更有效吗?由于它使用内部迭代器,它可能会短路,这有助于巨大的散列,但它具有使用(全局!)散列迭代器的一般缺点。 each() 是一个错误,IMO。
  • @tsee:对于更大的哈希值更有效,因为它不会创建中间值列表。这是获得非常大(例如绑定)哈希的唯一方法。当然,应该记住,程序中的每个散列都有一个迭代器,这是设计的。
  • 只有当 ref 指向另一个散列时它才是多维的;或者,可以说是另一个数组。它肯定不会是多维的,因为它有一个全局引用、子引用或标量引用。这是不对的。
  • @eugene y -- 实际上,values 也不会创建对哈希值的引用列表。 perl -e'my %foo=(bar=>'baz'); $_=1 for values %foo; use Data::Dumper; die Dumper \%foo',实际上,您的确实需要将每个键和值复制到不同的本地标量,即$key$value
【解决方案2】:

您也可以为此firstgrep

use List::Util 'first';
say 'is multi-dimensional' if first { ref } values %$hash_ref;

# explicitly check for HASH ref this time
my $how_many_md_hashes = grep { 'HASH' eq ref } values %$hash_ref;

注意。 firstList::Util 核心模块的一部分)短路,因此非常适合条件语句,并且可能是所有可能选项中最快的。

/I3az/

【讨论】:

  • 如果您只关心真实性而不是匹配的实际值,您可以使用 'any' 而不是 'first':use List::MoreUtils 'any'; my $is_multi_dimensional = any { ref } values %$hash_ref;
【解决方案3】:

你可以试试这个来了解 Perl 哈希的深度:

#!/usr/bin/perl
use strict;
my $hash_ref = {

  'hashes' => {
    'h1' => { 'klf' => '1', 'moomooland' => '1' },
    'h2' => { 'klf' => '2', 'moomooland' => '2' },
    'h3' => { 'klf' => '3', 'moomooland' => '3' }
  },

  'keys' => {
    'k1' => 'key1',
    'k2' => 'key2',
    'k3' => 'key3'
  }

};
print_nested_hash($hash_ref, 0);

sub print_nested_hash {
    my $hash_ref = shift;
    my $depth = shift;
    foreach my $key (sort keys %{$hash_ref}) {
        print '    ' x $depth, $key, "\n";

        if (ref($hash_ref->{$key}) eq "HASH") {
            print_nested_hash($hash_ref->{$key}, $depth+1);
        }
    }
} 

输出:

hashes
    h1
        klf
        moomooland
    h2
        klf
        moomooland
    h3
        klf
        moomooland
keys
    k1
    k2
    k3

【讨论】:

    猜你喜欢
    • 2012-09-06
    • 1970-01-01
    • 2015-01-17
    • 2011-01-08
    • 2019-06-01
    • 2011-05-19
    • 1970-01-01
    • 2014-05-27
    • 2011-12-10
    相关资源
    最近更新 更多