Zac*_*ack 4 perl hash perl-data-structures
让我们假设我有两个哈希.其中一个包含一组数据,只需要保留显示在另一个哈希中的内容.
例如
my %hash1 = (
test1 => { inner1 => { more => "alpha", evenmore => "beta" } },
test2 => { inner2 => { more => "charlie", somethingelse => "delta" } },
test3 => { inner9999 => { ohlookmore => "golf", somethingelse => "foxtrot" } }
);
my %hash2 = (
major=> { test2 => "inner2",
test3 => "inner3" } );
Run Code Online (Sandbox Code Playgroud)
我想要做的是删除hash1中的整个subhash,如果它不作为hash2 {major}中的键/值存在,最好没有模块."innerX"中包含的信息无关紧要,只需要保持不变(除非删除子哈希然后它就会消失).
在上面的示例中,在执行此操作之后,hash1将如下所示:
my %hash1 = (
test2 => { inner2 => { more => "charlie", somethingelse => "delta" } },
);
Run Code Online (Sandbox Code Playgroud)
它删除hash1 {test1}和hash1 {test3},因为它们与hash2中的任何内容都不匹配.
这是我目前尝试过的,但它不起作用.也不是最安全的事情,因为我在尝试从中删除哈希时循环哈希.但是我在每个都删除应该没问题?
这是我尝试这样做的,但是perl抱怨:
在使用"严格参考"时,不能使用字符串("inner1")作为HASH参考
while(my ($test, $inner) = each %hash1)
{
if(exists $hash2{major}{$test}{$inner})
{
print "$test($inner) is in exists.\n";
}
else
{
print "Looks like $test($inner) does not exist, REMOVING.\n";
#not to sure if $inner is needed to remove the whole entry
delete ($hash1{$test}{$inner});
}
}
Run Code Online (Sandbox Code Playgroud)
你很亲密 请记住,这$hash2{major}{$test}是一个标量,而不是哈希引用.
#! /usr/bin/perl
use strict;
use warnings;
my %hash1 = (
test1 => { inner1 => { more => "alpha", evenmore => "beta" } },
test2 => { inner2 => { more => "charlie", somethingelse => "delta" } },
test3 => { inner9999 => { ohlookmore => "golf", somethingelse => "foxtrot" } }
);
my %hash2 = (
major => { test2 => "inner2",
test3 => "inner3" }
);
foreach my $k (keys %hash1) {
my $delete = 1;
foreach my $inner (keys %{ $hash1{$k} }) {
$delete = 0, last if exists $hash2{major}{$k} &&
$hash2{major}{$k} eq $inner;
}
delete $hash1{$k} if $delete;
}
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%hash1;
Run Code Online (Sandbox Code Playgroud)
这行开头$delete = 0, ...有点儿很可爱.它相当于$delete = 0; last;另一个条件,但它已经嵌套了两次.我不想建立一个matryoshka娃娃,我使用了一个语句修饰符,但顾名思义,它修改了一个语句.
这就是Perl的逗号运营商所在:
二进制
,是逗号运算符.在标量上下文中,它评估其左参数,抛出该值,然后计算其右参数并返回该值.这就像C的逗号运算符一样.
在这种情况下,左参数是表达式$delete = 0,右参数是last.
条件似乎不必要地挑剔,但是
... if $hash2{major}{$k} eq $inner;
Run Code Online (Sandbox Code Playgroud)
在探测%hash2(test1/inner1,例如)中未提及的测试时,会产生未定义值警告.运用
.. if $hash2{major}{$k} && $hash2{major}{$k} eq $inner;
Run Code Online (Sandbox Code Playgroud)
%hash2如果其"内部名称"是假值(如字符串),则会错误地删除提及的测试"0".是的,exists在这里使用可能是不必要的挑剔,但不知道你的实际哈希键,我选择了保守的路线.
输出:
$VAR1 = {
'test2' => {
'inner2' => {
'somethingelse' => 'delta',
'more' => 'charlie'
}
}
};
虽然您没有违反此规定,但请注意以下与使用相关的警告each:
如果在迭代时添加或删除哈希的元素,则可能会跳过或复制条目,因此不要.例外:删除最近返回的项目总是安全的
each,这意味着以下代码将起作用:Run Code Online (Sandbox Code Playgroud)while (($key, $value) = each %hash) { print $key, "\n"; delete $hash{$key}; # This is safe }
更新:搜索哈希就像它们是数组一样(通过说"...线性而不是对数"来打动你的CS书呆子朋友)是一个红旗,上面的代码就是这样.一个更好的方法,结果类似于Penfold的答案,是
%hash1 = map +($_ => $hash1{$_}),
grep exists $hash2{major}{$_} &&
exists $hash1{$_}{ $hash2{major}{$_} },
keys %hash1;
Run Code Online (Sandbox Code Playgroud)
在很好的声明式风格中,它描述了所需的内容%hash1,即
%hash1应该提及的第一级键$hash2{major},和$hash2{major}对应于每个第一级密钥的值本身应该是该密钥的子密钥%hash1(哇,令人目不暇接.我们需要英文多个占位符变量!)
+($_ => $hash1{$_})对于可怜的解析器,一元加上消除歧义,因此它知道我们希望将表达式视为"对".如果需要,请参阅perlfunc文档map的结尾以了解其他情况.
| 归档时间: |
|
| 查看次数: |
3455 次 |
| 最近记录: |