如何在散列而不是数组上使用 Perl grep?

如何在散列而不是数组上使用 Perl grep?

我正在学习 Perl。我已经能够grep在数组上使用,语法非常简单,就像这样例子:

use strict; use warnings;

my @names = qw(Foo Bar Baz);
my $visitor = <STDIN>;
chomp $visitor;
if (grep { $visitor eq $_ } @names) {
   print "Visitor $visitor is in the guest list\n";
} else {
   print "Visitor $visitor is NOT in the guest list\n";
}

但是,我想知道是否有一种同样简单的方法可以grep在哈希上使用无需编写循环来迭代哈希中的每个项目

这是我正在使用的结构的一些示例数据。在分配 URI 之前,我想检查是否有任何项目已经具有该 uri 值。例如,我想分配ww1.example.com给 item v2rbz1568,但前提是没有其他项目的 uri 值为ww1.example.com。我怎样才能在 Perl 中有效地完成这个任务?

{
    "0y7vfr1234": {
        "username": "[email protected]",
        "password": "some-random-password123",
        "uri": "ww1.example.com",
        "index": 14
    },
    "v2rbz1568": {
        "username": "[email protected]",
        "password": "some-random-password125",
        "uri": "ww3.example.com",
        "index": 29
    },
    "0zjk1156": {
        "username": "[email protected]",
        "password": "some-random-password124",
        "uri": "ww2.example.com",
        "index": 38
    }
}

我在 Linux 上使用 perl 5 版本 30。

答案1

至少有两个选择:

  1. 您(仅)拥有您在问题中设想的数据结构。然后,每次你想找到匹配项时,你都必须遍历整个“列表”。不过,您不必编写循环,您可以使用该map函数:
use strict; use warnings;
my %entries = (
    '0y7vfr1234' => {
        'username' => '[email protected]',
        'password' => 'some-random-password123',
        'uri' => 'ww1.example.com',
        'index' => 14
    },
    'v2rbz1568' => {
        'username' => '[email protected]',
        'password' => 'some-random-password125',
        'uri' => 'ww3.example.com',
        'index' => 29
    }
);
my $uri = <STDIN>;
chomp $uri;
if (grep { $uri eq $_ } map { $_->{'uri'} } values %entries) {
   print "URI $uri is in the list\n";
} else {
   print "URI $uri is NOT in the list\n";
}
  1. 您可以在哈希中管理一个单独的索引,以便可以进行快速查找。索引意味着您有一个单独的哈希映射 URI 到实际哈希的项目:
use strict; use warnings;
my %entries = (
    '0y7vfr1234' => {
        'username' => '[email protected]',
        'password' => 'some-random-password123',
        'uri' => 'ww1.example.com',
        'index' => 14
    },
    'v2rbz1568' => {
        'username' => '[email protected]',
        'password' => 'some-random-password125',
        'uri' => 'ww3.example.com',
        'index' => 29
    }
);
my %index = map { $entries{"uri"} => $_ } keys %entries;

my $uri = <STDIN>;
chomp $uri;
my $item = $index{$uri};
if (defined($item)) {
   print "URI $uri is in the list\n";
} else {
   print "URI $uri is NOT in the list\n";
}

这也很方便,因为$item如果您除了检查哈希是否存在之外还想访问哈希中已存在的条目,则可以直接获得查找结果,例如print "Index: ",$entries{$item}->{'index'},"\n";

在第二种情况下,每次在“列表”中添加/更新/删除 URI 时,您都必须手动更新索引:

$entries{"v84x9v8b9"} = { uri => "ww49", ... };
$index{"ww49"} = "v84x9v8b9";

相关内容