我有这段代码可以将行放入%data
中。 DATA中的一行(最后一行)是重复的,因此我不希望将其添加到%data
中。在将行推入app_id
之前,如何检查ci_name
和%data
组合尚不存在?像
push .. unless {app_id already exists}
要修改的代码:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %data;
while( <DATA> ) {
chomp;
next if /app_id/;
my ($app_id,$ci_name,$app_name) = split /,/;
push @{$data{$ci_name}}, {app_id => $app_id, app_name => $app_name };
}
print Dumper(\%data);
__DATA__
app_id,ci_name,app_name
1234,hosta7,Managed File Transfer
1235,hosta7,Patrtol
1236,hosta7,RELATIONAL DATA WAREHOUSE
1237,hosta7,Managed File Transfer
1238,hosta7,Initio Application
1239,hosta7,Data Warehouse Operations Infrastructure
2345,hostb,Tableou
2345,hostb,Tableou
答案 0 :(得分:3)
您可以暂时使用HoH代替HoA。
=
以上内容保留第一个重复项,并且不保留顺序。将my %seen;
my @uniq = grep !$seen{$_}++, @values;
更改为#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
<DATA>; # Skip header.
my %data;
my %seen;
while (<DATA>) {
chomp;
my ($app_id, $ci_name, $app_name) = split /,/;
push @{ $data{$ci_name} }, { app_id => $app_id, app_name => $app_name }
if !$seen{$ci_name}{$app_id}++;
}
print Dumper(\%data);
以保留最后的重复项。继续阅读以获取保留订单的解决方案。
以下是在保留订单的同时删除重复项的常用方法:
<DATA>
我们可以使这种习语适应我们的需求。
app_id
上面保留了第一个重复项,并且保留了顺序。
这两个解决方案的速度均为O(N),而先前发布的解决方案的速度为O(N 2 ),因此该解决方案的伸缩性更好。不过,老实说,除非重复很多,否则以前发布的解决方案的实际速度为O(N)。
请注意如何在循环之前添加%
?这比跳过行中任何地方包含cd "bin\drivers" && for %%i in (*.*) do if not %%i == lol.exe del %%i
的所有行要好得多!
答案 1 :(得分:2)
您可以将grep()与一个块一起使用,该块检查app_id
是否等于要插入的块。
...
push @{$data{$ci_name}}, {app_id => $app_id, app_name => $app_name } unless grep { $_->{'app_id'} == $app_id; } @{$data{$ci_name}};
...
答案 2 :(得分:0)
如果要保留所有记录(改编自@ikegami):
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
<DATA>; # Skip header.
my %data;
while (<DATA>) {
chomp;
my ($app_id, $ci_name, $app_name) = split /,/;
push @{ $data{$ci_name}{$app_id} }, { app_id => $app_id, app_name => $app_name };
}
print Dumper(\%data);
但是最好进行编码:
$data{$ci_name}{$app_id}{$app_name}++;