我在试图弄清楚如何解决这个问题时遇到了一些麻烦。我有一个看起来像的文件:
1 1 1 1 1 1 2 a
1 1 1 3 4 4 4 a
1 1 1 4 4 4 2 a
2 2 2 3 3 3 2 b
2 2 2 1 1 1 1 b
其中,我想计算前3个数字连续重复多少次。就像在我将数据集加载到perl中一样,它会吐出来:
3
2
作为字符串' 1 1 1'在一行的开头连续3次被发现,字符串' 2 2 2'被发现连续2次开始一条线。这两个字符串可能会出现在文件的后面,这会使事情变得复杂。同样,我也不知道起始字符串是什么,并且它会有所不同。
老实说,我真的很困惑如何攻击它。如果有人可以帮助概念化这个/给我一些伪代码来帮助,那就太好了。
编辑:根据鲍罗丁的回答,这完全符合我的要求。但是,如果我想打印计数加上哪个字母,我该怎么做?到目前为止,my ( $inp, $outp) = qw / OUT2 OUTFILE/;
open my $input, '<', $inp or die;
open my $output, '>', $outp or die;
my ($last_key, $count);
while ( <$input> ) {
my $key = join ' ', (split)[0..2];
my $id = join ' ', (split)[7];
if ( defined $last_key and $key eq $last_key ) {
++$count;
}
else {
printf "%s %d $id\n", $last_key, $count if defined $last_key;
$last_key = $key;
$count = 1;
}
printf "%s %d $id\n", $last_key, $count if eof;
}
给出了:
1 1 1 3 b
2 2 2 2 b
这不是我瞄准的目标。
谢谢!
EDIT2
得到了我想要的工作。通常,所需要的只是寻求帮助来自己解决问题。
更新的代码:
my ( $inp, $outp) = qw / OUT2 OUTFILE/;
open my $input, '<', $inp or die;
open my $output, '>', $outp or die;
my ($last_key, $count, $last_id);
while ( <$input> ) {
my $key = join ' ', (split)[0..2];
my $id = join ' ', (split)[7];
if ( defined $last_key and $key eq $last_key ) {
++$count;
}
else {
printf "%s %d $last_id\n", $last_key, $count if defined $last_key;
$last_key = $key;
$count = 1;
$last_id = $id;
}
printf "%s %d $id\n", $last_key, $count if eof;
}
在:
1 1 1 1 1 1 2 a
1 1 1 3 4 4 4 a
1 1 1 4 4 4 2 a
2 2 2 3 3 3 2 b
2 2 2 1 1 1 1 b
3 3 3 2 5 4 2 c
给出:
1 1 1 3 a
2 2 2 2 b
3 3 3 1 c
全部谢谢!
答案 0 :(得分:2)
你只需要跟踪上一行,或者至少是它的相关部分,以及它被看到的次数:
use strict;
use warnings;
my $count = 0;
my $last_prefix = '';
my $last_value = '';
while (my $line = <>) {
my ($prefix, $value) = $line =~ /^(\S+\s+\S+\s+\S+).*(\S+)/ or die "malformed line $line";
if ($prefix ne $last_prefix) {
if ($count) {
print "$count $last_value\n";
}
$last_prefix = $prefix;
$last_value = $value;
$count = 0;
}
++$count;
}
if ($count) {
print "$count $last_value\n";
}
答案 1 :(得分:1)
这只需要从前三个字段形成一个键并计算它们出现的次数,每当键发生变化或文件结束时打印一行输出
use strict;
use warnings;
my ($last_key, $count);
while ( <DATA> ) {
my $key = join ' ', (split)[0..2];
if ( defined $last_key and $key eq $last_key ) {
++$count;
}
else {
printf "%s -> %d\n", $last_key, $count if defined $last_key;
$last_key = $key;
$count = 1;
}
printf "%s -> %d\n", $last_key, $count if eof;
}
__DATA__
1 1 1 1 1 1 2 a
1 1 1 3 4 4 4 a
1 1 1 4 4 4 2 a
2 2 2 3 3 3 2 b
2 2 2 1 1 1 1 b
3 3 3 1 1 1 1 c
1 1 1 -> 3
2 2 2 -> 2
3 3 3 -> 1
要在输出数据中包含最后一列,只需更改
即可my $key = join ' ', (split)[0..2]
到
my $key = join ' ', (split)[0..2,-1]
1 1 1 a -> 3
2 2 2 b -> 2
3 3 3 c -> 1
答案 2 :(得分:0)
这是一种方法:
# Open file and loop through lines
open (INFH, '<', "num.txt");
my $count = 0;
my $str;
my %countHash;
while(<INFH>){
# split the line using space characters to get first three numbers
my @numArray = split(' ', $_);
#Concatenating first three numbers as a string to use as key
$key = "$numArray[0]" . "$numArray[1]" . "$numArray[2]";
#If the combination exists, update the value by adding 1. Else add new
if (!exists $countHash{$key}){
$countHash{$key} = 1;
}else{
$countHash{$key} += 1;
}
}
print %countHash;
如果我能做得更好,我会更新。