1

我有两个关联的数组。第一个具有哈希中的“键”,第二个具有“值”。数组中每个“键”都有多个实例,与每个键关联的值可以是yes,也可以是no。一个简单的例子:

@1 = ('NET1020, NET0190, NET1020, NET0230,
       NET1020, NET1639, NET0820, NET1639');

@2 = ('yes, yes, no, no,
       yes, no, yes, no');

请注意,与“键”NET1020 关联的值是 yes 和 no。

我需要使用@1 来第一次查找重复项并将它们从两个数组中删除,如果@2 中的一个值不是,那么这需要是@1 中“键”的值。如果不是,那么该值可以是yes。基本上我需要结束的是:

%1-2 = (
    "NET1020"  => "No", 
    "NET0190"  => "Yes",
    "NET0230"  => "No",
    "NET1639"  => "No",
    "NET0820"  => "Yes",
);

我希望我的解释足够清楚。我是一个 perl 新手,不知道从哪里开始。

谢谢你的帮助。

4

5 回答 5

2
my @names = split /\s*,\s*/, 'NET1020, NET0190, NET1020, NET0230, NET1020, NET1639, NET0820, NET1639';
my @flags = map { $_ eq 'yes' }
            split /\s*,\s*/, 'yes, yes, no, no, yes, no, yes, no';

my %flags;
for (0..$#names) {
   if (exists($flags{ $names[$_] })) {
      $flags{ $names[$_] } &&= $flags[$_];
   } else {
      $flags{ $names[$_] } = $flags[$_];
   }
}

print($_, ": ", $flags{$_} ? "Yes" : "No", "\n")
   for sort keys %flags;

您不应该使用yesandnoYesand No。该解决方案在输入时将yesand转换no为更合适的真假。如果你想输出真假,你会在输出时处理它,如图所示YesNo

你甚至可以看到在这个小工作中使用真假的好处。它通过对具有相同名称的条目的标志进行与运算来工作。(ANDing 时,False 胜出。ORing 时 True 胜出。)

于 2014-03-04T16:18:07.813 回答
0

数组内容的顺序重要吗?

如果没有,我建议使用哈希:

    my %hash = ();
    for my $i (0 .. $#array1)
    {
          $hash{ $array1[$i] } =  $array2[$i]; 
    }
@filtered1 = keys %hash;
@filtered2 = values %hash;

注意:代码未经测试且未经验证

于 2014-03-04T15:40:39.033 回答
0

不清楚您是从 Perl 数组还是简单的逗号分隔字符串开始。我也不确定您是否希望将结果哈希值大写,或者与输入值相同。

这个简短的程序将满足您的需求。@a1它只是使用来自的每个键和 的初始值来分配哈希元素yes。此后,如果no遇到对应@a2的元素,则将元素的值设置为no

use strict;
use warnings;

my @a1 = qw{  NET1020 NET0190 NET1020 NET0230 NET1020 NET1639 NET0820 NET1639  };
my @a2 = qw{  yes     yes     no      no      yes     no      yes     no       };

my %data;
for my $i (0 .. $#a1) {
  my $key = $a1[$i];
  $data{$key} = 'yes' unless $data{$key};
  $data{$key} = 'no' if $a2[$i] eq 'no';
}

use Data::Dump;
dd \%data;

输出

{
  NET0190 => "yes",
  NET0230 => "no",
  NET0820 => "yes",
  NET1020 => "no",
  NET1639 => "no",
}
于 2014-03-04T16:21:56.163 回答
0

我不得不修改您的列表以更好地作为 Perl 工作。你给了一个多行字符串而不是一个数组。基本上,我的方法是非常标准的 CPAN。List::UtilList::MoreUtils

zip在列表之间创建基于顺序的对应关系。并pairs允许您将键值对处理为( $a, $b ).

use strict;
use warnings;
use List::Util      qw<pairmap>;
use List::MoreUtils qw<zip>;

my @_1 =  split /,\s*/ms, 
      ('NET1020, NET0190, NET1020, NET0230,
       NET1020, NET1639, NET0820, NET1639')
      ;

my @_2 = split /,\s*/ms, 
       ('yes, yes, no, no,
       yes, no, yes, no')
       ;
my %hash;
pairmap { 
    $hash{ $a } = $b unless ( $hash{ $a } // '' ) eq 'no'; 
} zip @_1, @_2
;

当然,pairwise可能更清洁:

use List::MoreUtils qw<pairwise>;
...
pairwise { 
    $hash{ $a } = $b unless ( $hash{ $a } // '' ) eq 'no'; 
} @_1, @_2
;
于 2014-03-04T16:09:59.473 回答
0

只需遍历这些值并根据需要添加/更新您的哈希。

1.如果key已经存在,只有在现有值不为'no'时才更新它

2 如果密钥不存在,则将其添加到哈希中

#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

my @arr1 = 
   qw(NET1020 NET0190 NET1020 NET0230 NET1020 NET1639 NET0820 NET1639);
my @arr2 = 
   qw(yes yes no no yes no yes no);

my %h;
KEY:
foreach my $i ( 0 .. $#arr1 ) {
   # get the values out of your parallel arrays
   my $key = $arr1[$i];
   my $val = $arr2[$i];

   # if the key is already in your hash and does not have this value
   if (exists $h{$key} && $h{$key} ne $val) {
      # don't change the key if the value is currently 'no'
      next KEY if lc $h{$key} eq 'no';

      # update if the value was not yes, meaning this is going from yes -> no
      $h{$key} = $val;
   }

   # if the key didn't exist already add it
   $h{$key} = $val;
}
print Dumper \%h;

__END__   
{ 'NET0190' => 'yes',
  'NET1639' => 'no',
  'NET0230' => 'no',
  'NET0820' => 'yes',
  'NET1020' => 'no'
};

如果没有重复项,您可以在一行中使用hash-slice执行此操作:

my %h; 
@h{@arr1} = @arr2; 
于 2014-03-04T16:00:44.107 回答