Perl Loop概念化

时间:2015-07-23 21:19:15

标签: perl

我在试图弄清楚如何解决这个问题时遇到了一些麻烦。我有一个看起来像的文件:

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

全部谢谢!

3 个答案:

答案 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;

如果我能做得更好,我会更新。