我有一张这样的表
symbol length id
A 10 id_1
A 15 id_2
A 15 id_3
B 20 id_4
B 25 id_5
... ... ...
我想在新表中打印以下内容
symbol length id
A 15 id_2; id_3
B 25 id_5
... ... ...
所以我想遍历symbol
列。当此列中存在重复值时,我想打印数字长度值最大的行(例如:符号B)。当最大length
值相等时,我想合并id
列中的值(例如:符号A)并打印此新行。
我应该如何在perl中执行此操作?
答案 0 :(得分:2)
perl中用于合并重复项的工具是一个哈希。散列是键值对,但有用的部分是 - 值可以是数组(引用)。
我建议这样的事情:
#!/usr/bin/perl
use strict;
use warnings;
my %length_of;
my %ids_of;
my $heading_row = <DATA>;
while (<DATA>) {
my ( $symbol, $length, $id ) = split;
if ( not defined $length_of{$symbol} or $length_of{$symbol} < $length ) {
$length_of{$symbol} = $length;
}
push( @{ $ids_of{$symbol}{$length} }, $id );
}
print join( "\t", "symbol", "length", "ids" ), "\n";
foreach my $symbol ( sort keys %ids_of ) {
my $length = $length_of{$symbol};
print join( "\t",
$symbol,
$length,
join( "; ", @{ $ids_of{$symbol}{$length} } ) ),
"\n";
}
__DATA__
symbol length id
A 10 id_1
A 15 id_2
A 15 id_3
B 20 id_4
B 25 id_5
这是做什么的 - 迭代您的数据,并保存最高length
值(在%length_of
中)。它还存储每个ID - 按符号和长度(在%ids_of
中)。它保留了所有这些,所以如果您拥有大量数据,这可能效率不高。
答案 1 :(得分:2)
记住最后一个符号和长度并累积id:
#! /usr/bin/perl
use warnings;
use strict;
my ($last_l, $last_s, @i);
sub out {
print "$last_s\t$last_l\t", join(";", @i), "\n"
}
while (<>) {
my ($s, $l, $i) = split;
out() if $last_s and $s ne $last_s;
undef @i if $last_l < $l;
push @i, $i;
$last_s = $s;
$last_l = $l;
}
out();
答案 2 :(得分:0)
此方法通过使用symbol
和length
列中的值作为键并将id
列中的值添加为数组引用来构建hash of hashes of arrays。对于您提供的简单数据集,实际上并不需要这样复杂的数据结构,但在未对数据进行排序的情况下,下面显示的方法可能更灵活。
我使用List::Util
中的max
函数(它是核心发行版的一部分)来获取每个length
的最大symbol
值,以及{{1帮助可视化事物。
Data::Dumper
<强>输出强>:
use Data::Dumper ;
use List::Util 'max';
use v5.16;
my (%hash, @lines) ;
while ( <DATA>) {
chomp ;
next if $. == 1 ;
push @lines, [ split ] ;
}
for (@lines) {
push @{ $hash{ $_->[0] }{ $_->[1] } }, $_->[2] ;
}
say "This is your %hash:\n", Dumper \%hash;
for my $symbol ( keys %hash ) {
my $max = max ( keys $hash{$symbol} ) ;
say "$symbol \t", "$max \t", join "; ", @{ $hash{$symbol}{$max} };
}
__DATA__
symbol length id
A 10 id_1
A 15 id_2
A 15 id_3
B 20 id_4
B 25 id_5