首页 > 解决方案 > 比较两个文件以查找常见且唯一的条目

问题描述

我想比较两个文件中的条目。

第一个文件

ch1 12345 ch1 12900 Del
ch1 13000 ch1 13689 Del
ch2 14567 ch2 14905 Del
ch4 23001 ch4 26019 Del

第二个文件

ch1 12309 ch1 12865 
ch2 14531 ch2 14871 
ch3 16909 ch3 16990
ch4 45401 ch4 45810

我已经编写了一个 Perl 程序,在另一个数组中循环一个数组并识别公共条目,但是使用这种方法我无法识别唯一条目。

标签: arraysperlhash

解决方案


您可以尝试以下程序。

如果您改变了双方必须发生多少次的想法,请更改$limit变量的值。也许只有 1 就足够了?

use strict; use warnings;
# Count text occurrences in 2 files

my %counts;         # Hash of arrays (occurrence counters)

sub inputProcess {
  # Process input file
  my $fn = shift;   # File name
  my $n = shift;    # Counter index
  open (my $fh, '<', $fn) or die "Can't open $fn: $!";
  while (<$fh>) {
    chomp;
    $counts{$_}[$n]++;
  }
}

sub readCounts {
  # Read counters, substituting 0 if any does not exist
  my $cnt = shift;  # Reference to array of counters
  my @v = (0, 0);
  foreach my $i ( 0 .. $#v ) {
    $v[$i] = $cnt->[$i] if exists $cnt->[$i];
  }
  return @v;
}

sub printUniq {
  # Print unique entries for the given counter
  my $myCnt = shift;            # "My" counter
  my $otherCnt = 1 - $myCnt;    # The "other" counter
  print "Unique entries from file $myCnt:\n";
  foreach my $key (sort keys %counts) {
    my $val = $counts{$key};
    my @v = readCounts($val);
    if ($v[$myCnt] > 0 && $v[$otherCnt] == 0) {
      printf "%s\n", $key;
    }
  }
}

sub printCommon {
  # Print common entries for both files
  print "Common entries for both files:\n";
  my $limit = 50;
  foreach my $key (sort keys %counts) {
    my $val = $counts{$key};
    my @v = readCounts($val);
    if ($v[0] >= $limit && $v[1] >= $limit) {
      printf "%s\n", $key;
    }
  }
}

inputProcess('Inp1.txt', 0);
inputProcess('Inp2.txt', 1);
print "All entries and counts\n";
foreach my $key (sort keys %counts) {
  my $val = $counts{$key};
  my ($v0, $v1) = readCounts($val);
  printf "%-16s / %3d, %3d\n", $key, $v0, $v1;
}
printUniq(0);
printUniq(1);
printCommon();

这个想法是使用(引用)数组的散列。密钥只是从文件中读取的条目。每个数组(散列中的值)包含 2 个计数器,用于两个文件。

该程序会打印已排序的条目,但如果您愿意,只需删除排序即可。

编写上面的程序,我假设每一行都是一个单独的条目。如果不是这种情况,则相应地修改inputProcess函数。

还有一点:第一个文件在每行的末尾包含Del,而第二个文件没有。这样的条目(整行)不会“匹配”。


推荐阅读