【问题标题】:Find an array element from the value of an element of the hashes it contains从它包含的哈希元素的值中找到一个数组元素
【发布时间】:2017-01-23 06:12:08
【问题描述】:

我正在尝试对哈希数组@aoh 进行排序,目前我提取某些键的值并对这个列表进行排序。我从每个哈希中提取键 description 的值。

现在我希望能够识别数组中的哪个元素对应于哈希元素的给定值。

我想我需要使用哈希引用,但是怎么做呢?

我的代码示例如下

#!/usr/bin/perl

use warnings;
use strict;

my %h1 = ('description', 'great one');
my %h2 = ('description', 'fool');
my %h3 = ('description', 'easy');
my %h4 = ('description', 'intermediate');
my %h5 = ('description', 'hard');
my %h6 = ('description', 'beauty');
my %h7 = ('description', 'dark');
my %h8 = ('description', 'yellow');
my %h9 = ('description', 'red');

my @aoh = ( %h1, %h2, %h3, %h4, %h5, %h6, %h7, %h8, %h9 );

my @vals;

while ( my ($index, $value) = each @aoh ) {

    if ( $aoh[$index] ne 'description' ) {
        push @vals, $aoh[$index];
    }
}

my @sorted = sort @vals;

printf "@sorted\n";

在一个结果中,我想像这样得到@sorted_aoh

@sorted_aoh = (
    'description'->'beauty',
    'description'->'dark',
    'description'->'easy',
    'description'->'fool',
    'description'->'great one',
    'description'->'one',
    'description'->'hard',
    'description'->'intermediate',
    'description'->'red',
);

【问题讨论】:

  • 如果您需要“确定数组的哪个元素对应于哈希元素的给定值”,那么您不需要您询问的排序数组,而是像鲍罗丁的回答中的查找机制。另外,我建议阅读有关这些内容的一些文档。参考教程是perlreftut,对于复杂的数据结构,有说明书perldsc
  • @zdim,感谢您的提示)我会研究这些文档
  • 以防万一……我认为您的“描述”实际上是不同的文本,并不总是同一个词。但是,如果你真的有一对散列,并且每个散列都有 same word 作为键,那么你应该改变设计(不需要两个数据结构,但使用数组或一个哈希)。此外,通过散列 values 对数组进行排序似乎很尴尬——你将如何查找它们?你将如何检索值hard 的元素?您必须进行迭代,否认散列的目的。也许你应该解释这一切的目的。
  • @zdim,在这种情况下表示的数据结构是真实数据的抽象和精简版本(如讨论所示 - 不幸的是,不是最成功的)。在实际任务中它更复杂,但(正如我所想)澄清问题 - 这些数据应该足够了。
  • 好的,感谢您确认 :) 我仍然不确定按哈希值排序的数组的实用性,但这可能已经在抽象中丢失了——您知道您的真实数据和问题。

标签: arrays perl hash


【解决方案1】:

如前所述,您的数组@aoh 不是散列数组,它只是一个标量数据数组。看起来是这样的

(
  "description",
  "great one",
  "description",
  "fool",
  "description",
  "easy",
  "description",
  "intermediate",
  "description",
  "hard",
  "description",
  "beauty",
  "description",
  "dark",
  "description",
  "yellow",
  "description",
  "red",
)

哈希的标识已丢失,数据被扁平化为单个列表。 Perl 使用 references

实现嵌套结构

你没有说你的数据来自哪里,而是从一些单独命名的哈希开始,然后将它们的引用复制到一个数组中,最好直接使用数组的元素,所以$h1{description} 变为 $aoh[0]{description} 等等。

此解决方案以 @aoh 开始,这样构建,因此没有命名哈希。

(顺便说一句,像%h1@aoh 这样的名称很差。标识符应该描述它们的内容概念,所以%people@sales_figures,而不是数据结构的性质它们是。Perl 中的前导 %@ 无论如何都会告诉你,但同样适用于任何语言的标识符。)

如果您经常发现自己需要在程序中访问与另一个值相对应的值,那么通常最好构建一个单独的散列来存储该关系。在这里,我构建了哈希 %desc_to_index,它将每个哈希的 description 元素的值与找到它的数组的索引相关联

我已经在最后转储了生成的结构,以便您可以看到它包含的内容

use strict;
use warnings 'all';

use List::Util 'max';

my @aoh = (
    { description => 'great one' },
    { description => 'fool' },
    { description => 'easy' },
    { description => 'intermediate' },
    { description => 'hard' },
    { description => 'beauty' },
    { description => 'dark' },
    { description => 'yellow' },
    { description => 'red' },
);

my %desc_to_index = map { $aoh[$_]{description} => $_ } 0 .. $#aoh;

{
    my $len = max map { length } keys %desc_to_index;

    for my $desc ( sort keys %desc_to_index ) {
        printf "%*s => %d\n", $len, $desc, $desc_to_index{$desc};
    }
}

输出

      beauty => 5
        dark => 6
        easy => 2
        fool => 1
   great one => 0
        hard => 4
intermediate => 3
         red => 8
      yellow => 7

我希望您同意构建%desc_to_indexmap 语句简洁明了,但它可能会让您感到困惑。如果你愿意,你可以写一个 for 循环来代替它做同样的事情,像这样

my %desc_to_index;

for my $i ( 0 .. $#aoh ) {
    my $desc = $aoh[$i]{description};
    $desc_to_index{$desc} = $i;
}

产生相同的结果

还要注意你的循环

while ( my ($index, $value) = each @aoh ) { ... }

在数组上使用each,这在此处是不寻常且不必要的。在 Perl 5 v12 之前它也不可用,如果循环过早退出,each 会产生尴尬的错误

您不需要each,因为您从不使用$value 的值,而是更喜欢$aoh[$index],这更常见。你的循环最好用像这样的简单for 循环来编写

for my $index ( 0 .. $#aoh ) { ... }

【讨论】:

    【解决方案2】:

    以下代码使用哈希引用数组,并根据description键的值对其进行排序。散列变量名称 (\%h1) 之前的反斜杠表示对该散列的引用。 sort 函数使用自定义比较块,查找 perldoc -f sort 了解更多信息,查找 perldoc perlcheat 了解如何使用参考。

            #!/usr/bin/perl
            use warnings;
            use strict;
    
            my %h1 = ('description', 'greate one');
            my %h2 = ('description', 'fool');
            my %h3 = ('description', 'easy');
            my %h4 = ('description', 'intermediate');
            my %h5 = ('description', 'hard');
            my %h6 = ('description', 'beauty');
            my %h7 = ('description', 'dark');
            my %h8 = ('description', 'yellow');
            my %h9 = ('description', 'red');
            my @aoh = (\%h1, \%h2, \%h3, \%h4, \%h5, \%h6, \%h7, \%h8, \%h9);
    
            my @sorted = sort { $a->{description} cmp $b->{description} } @aoh;
            use Data::Dumper;
            print Dumper(\@sorted);
    

    【讨论】:

    • 在您的解决方案的上下文中是一个子问题:如何将@aoh 动态转换为哈希引用数组。简单的循环转换在我手中不起作用!这需要将(%h1, %h2, %h3, %h4, %h5, %h6, %h7, %h8, %h9) 转换为(\%h1, \%h2, \%h3, \%h4, \%h5, \%h6, \%h7, \%h8, \%h9)
    • @John 我不知道有什么好的方法可以做到这一点。在 PERL 列表中,哈希是不可区分的,因为它们会自动分解为一系列键和值。您可能喜欢从一开始就使用 hashrefs,例如 my $h0 = { description => "yo value" };
    • 引用运算符\ 可分配的,所以my @aoh = ( \%h1, \%h2, \%h3, \%h4, \%h5, \%h6, \%h7, \%h8, \%h9 )可以更方便地写成my @aoh = \ ( %h1, %h2, %h3, %h4, %h5, %h6, %h7, %h8, %h9 );
    • @Borodin,谢谢,这是对案件理解的重要补充
    【解决方案3】:

    如何在 ll hashes 中利用唯一键名

    use Data::Dumper;
    my %h1 = ('description', 'great one');
    my %h2 = ('description', 'fool');
    my %h3 = ('description', 'easy');
    my %h4 = ('description', 'intermediate');
    my %h5 = ('description', 'hard');
    my %h6 = ('description', 'beauty');
    my %h7 = ('description', 'dark');
    my %h8 = ('description', 'yellow');
    my %h9 = ('description', 'red');
    my @aoh =  sort map { values $_ } (\%h1, \%h2, \%h3, \%h4, \%h5, \%h6, \%h7, \%h8, \%h9);
    my @hash = map { {"description" => $_}} @aoh;
    print  Dumper(\@hash);
    

    【讨论】:

    • 哦,谢谢.. 这个解决方案看起来不像 from@pii_ke 那样通用,因为如果我对每个哈希都做一些复杂的处理,那么这段代码的输出保持不变(只有对“描述” -> 值)。也许它只是我的初学者职位看起来如此
    • @JohnSmith:您必须将所有要求放入您的问题中。如果你想为你的问题添加一些重要的东西,那么你应该写一个新问题。接受一个答案而不是另一个答案是不公平的,因为它恰好满足了您未指定的要求。
    • k ,同意,@JohnSmith ,但是这个答案又不能是普遍的,因为对密钥“描述”的硬检查,我确实在我的 cmets abt 中提到了在所有其他哈希中利用唯一密钥。跨度>
    • @Birodin,我最初的问题是关于如何通过使用其中一个键的哈希值返回整个哈希值。我想,正如测试所示,使用不同的哈希数组(使用许多键值对)在决策中仍然没有返回整个哈希
    猜你喜欢
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 2019-07-30
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多