arrays - perl 比较数组元素并分组

标签 arrays perl compare

我带着另一个问题回来了。我有一个数据列表:

1 L DIELTQSPE H EVQLQESDAELVKPGASVKISCKASGYTFTDHE
2 L DIVLTQSPRVT H EVQLQQSGAELVKPGASIKDTY
3 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAN
4 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAG
5 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C LELDKWASL
6 L DIQMTQIPSSLSASLSIC H EVQLQQSGVEVKMSCKASGYTFTS
7 L SYELTQPPSVSVSPGSIT H QVQLVQSAKGSGYSFS P YNKRKAFYTTKNIIG
8 L SYELTQPPSVSVSPGRIT H EVQLVQSGAASGYSFS P NNTRKAFYATGDIIG
9 A MPIMGSSVAVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP
10 A MPIMGSSVVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP
11 L DVVMTQTPLQ H EVKLDESVTVTSSTWPSQSITCNVAHPASSTKVDKKIE
12 A DIVMTQSPDAQYYSTPYSFGQGTKLEIKR

我想比较每行的第三个元素和第五个元素,如果它们具有相同的第三个元素和第五个元素,则将它们分组。 例如,使用上面的数据,结果将是:

3: 3 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAN
   4 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAG
   5 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C LELDKWASL
9: 9 A MPIMGSSVAVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP
   10 A MPIMGSSVVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP

仅供引用,在实际数据中,第3、5、7个元素非常长。我把它们剪下来才能看到整体。

这就是我所做的,我知道这很笨拙,但作为初学者,我正在尽力而为。 问题是它只显示第一组“相同”组。 你能告诉我哪里出了问题和/或其他解决这个问题的好方法吗?

my $file = <>;
open(IN, $file)|| die "no $file: $!\n";
my @arr;
while (my $line=<IN>){
        push @arr, [split (/\s+/, $line)] ;
}
close IN;

my (@temp1, @temp2,%hash1);
for (my $i=0;$i<=$#arr ;$i++) {
    push @temp1, [$arr[$i][2], $arr[$i][4]]; 
    for (my $j=$i+1;$j<=$#arr ;$j++) {
        push @temp2, [$arr[$j][2], $arr[$j][4]];
        if (($temp1[$i][0] eq $temp2[$j][0])&& ($temp1[$i][1] eq $temp2[$j][1])) {
            push @{$hash1{$arr[$i][0]}}, $arr[$i], $arr[$j];
        }
    }
}
print Dumper \%hash1;

最佳答案

您似乎把这个问题变得过于复杂了,但这对于初学者来说很常见。详细考虑如何手动执行此操作:

  • 查看每一行。
  • 查看第三个和第五个字段是否与上一行相同。
  • 如果是,请打印它们。

循环和所有这些都是完全不必要的:

#!/usr/bin/env perl

use strict;
use warnings;

my ($previous_row, $third, $fifth) = ('') x 3;

while (<DATA>) {
  my @fields = split;
  if ($fields[2] eq $third && $fields[4] eq $fifth) {
    print $previous_row if $previous_row;
    print "\t$_";
    $previous_row = '';
  } else {
    $previous_row = $fields[0] . "\t" . $_;
    $third = $fields[2];
    $fifth = $fields[4];
  }
}

__DATA__
1 L DIELTQSPE H EVQLQESDAELVKPGASVKISCKASGYTFTDHE
2 L DIVLTQSPRVT H EVQLQQSGAELVKPGASIKDTY
3 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAN
4 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAG
5 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C LELDKWASL
6 L DIQMTQIPSSLSASLSIC H EVQLQQSGVEVKMSCKASGYTFTS
7 L SYELTQPPSVSVSPGSIT H QVQLVQSAKGSGYSFS P YNKRKAFYTTKNIIG
8 L SYELTQPPSVSVSPGRIT H EVQLVQSGAASGYSFS P NNTRKAFYATGDIIG
9 A MPIMGSSVAVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP
10 A MPIMGSSVAVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP
11 L DVVMTQTPLQ H EVKLDESVTVTSSTWPSQSITCNVAHPASSTKVDKKIE
12 A DIVMTQSPDAQYYSTPYSFGQGTKLEIKR

(请注意,我稍微更改了第 10 行,使其第三个字段与第 9 行匹配,以便在输出中获得指定的相同组。)

编辑:由于复制/粘贴错误而重复了一行代码。

编辑 2:为了回应评论,这里有第二个版本,它不假设应分组的行是连续的:

#!/usr/bin/env perl

use strict;
use warnings;

my @lines;
while (<DATA>) {
  push @lines, [ $_, split ];
}

# Sort @lines based on third and fifth fields (alphabetically), then on
# first field/line number (numerically) when third and fifth fields match
@lines = sort { 
  $a->[3] cmp $b->[3] || $a->[5] cmp $b->[5] || $a->[1] <=> $b->[1] 
} @lines;

my ($previous_row, $third, $fifth) = ('') x 3;
for (@lines) {
  if ($_->[3] eq $third && $_->[5] eq $fifth) {
    print $previous_row if $previous_row;
    print "\t$_->[0]";
    $previous_row = '';
  } else {
    $previous_row = $_->[1] . "\t" . $_->[0];
    $third = $_->[3];
    $fifth = $_->[5];
  }
}

__DATA__
1 L DIELTQSPE H EVQLQESDAELVKPGASVKISCKASGYTFTDHE
3 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAN
2 L DIVLTQSPRVT H EVQLQQSGAELVKPGASIKDTY
5 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C LELDKWASL
7 L SYELTQPPSVSVSPGSIT H QVQLVQSAKGSGYSFS P YNKRKAFYTTKNIIG
6 L DIQMTQIPSSLSASLSIC H EVQLQQSGVEVKMSCKASGYTFTS
9 A MPIMGSSVAVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP
8 L SYELTQPPSVSVSPGRIT H EVQLVQSGAASGYSFS P NNTRKAFYATGDIIG
11 L DVVMTQTPLQ H EVKLDESVTVTSSTWPSQSITCNVAHPASSTKVDKKIE
10 A MPIMGSSVAVLAIL B DIVMTQSPTVTI C EVQLQQSGRGP
12 A DIVMTQSPDAQYYSTPYSFGQGTKLEIKR
4 A ALQLTQSPSSLSAS B RITLKESGPPLVKPTCS C ELDKWAG

关于arrays - perl 比较数组元素并分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10898238/

相关文章:

perl - 为什么行终止符 `\r\n` 导致组不匹配?

javascript - 如何在 Javascript 中将数字变量与数组中的每个数字元素进行比较?

C++:从命令行读取和比较

arrays - UITableViewCell 删除然后所有复选标记 swift 消失

c - 数组在初始化时是什么样子的

windows - 在后台运行 bat 文件

perl - 使用父 'Exporter' 与使用导出器 'import' ;

java - 比较 Java 中的类类型有什么区别

php - 硬 PHP 螺母 : how to insert items into one associate array?

ios - 在 Swift 中为 UISearchController 链接数组