/ /行のある位置にある文字を同じ位置にある残りの行と比較する簡単な方法(Perl)-perl、比較、位置、文字

行の位置にある文字を同じ位置にある残りの行と比較する簡単な方法(Perl)-perl、比較、位置、文字

たくさんの行を含むファイルがあり、特定の列のすべての文字がPerlのファイルの残りの部分と一致するかどうかを比較したいと思います。たとえば、ファイルがある場合:

abcdefg
avcddeg
acbdeeg

ファイルは次のようになります a、d、g 一致し、位置を返します。

私はperlで2D配列を使用してファイル全体をトラバースして比較することを考えていましたが、面倒になる可能性があります。誰かがこれを行う簡単な方法がありますか?

ありがとう

回答:

回答№1の場合は7

これは、ビット演算を使用した巧妙な(そして高速な)ソリューションです。 a & b & ... & z 等しい a | b | ... | z すべての場合に限り a, b, ..., z 等しいです。

# read first line:
chomp( $_ = <> );
my $join = my $meet = $_;

# read other lines:
while( <> ) {
chomp;
$join |= $_;
$meet &= $_;
}

# print matching columns:
foreach my $i ( 0 .. length($meet) - 1 ) {
my $a = substr $join, $i, 1;
my $b = substr $meet, $i, 1;
print "$i: $an" if $a eq $b;
}

テスト入力:

abcdefg
avcddeg
acbdeeg

出力:

0: a
3: d
6: g

追伸このソリューションは、線の長さが異なる場合でも機能します。最短行の終わりを超える列は、一致するとは見なされません。


回答№2の場合は1

完全に一致するかどうかを判断するには、すべてのインデックスを他のインデックスと比較する必要があるため、面倒な作業を減らす方法がわかりません。サブストリングを利用することで、2D配列の作成を回避できます。

my @matchedIndexes;
my $pattern = "abcdefg";
INDEX:
for $index ( 0 .. ( length($pattern) - 1 ) ){
for $line (@remainingLines){
#if we find a nonmatch at the index, cut out.
if ( !(substr($line, $index, 1) == substr($pattern, $index, 1) ){
next INDEX;
}
}
#if we made it here without cutting out, the whole set of lines matched.
push @matchedIndexes, $index;
}

回答№3の場合は1

ビット単位のxorを使用できます ^。 2つの文字列を排他的論理和すると、文字列が同一の位置にゼロが残ります。

use warnings;
use strict;

my $previous;
my $first = 1;
while (<>) {
chomp;
$previous = $_ if $first;
undef $first;
my $in = $previous ^ $_;
my $p;
my @u = unpack "c*", $in;
$p .= $u[$_] ? " " : substr $previous, $_, 1 for 0 .. $#u;
$previous = $p;
last if $p =~ /^ +$/; # no more matches possible
}

print pos $previous, ": $1n" while $_ = $previous =~ /(S)/g;

回答№4の場合は1

効果的ではなく、メモリを大量に消費しますが、かなり読みやすく、簡単です。

use strict;use warnings;

my $lead = <DATA>;
chomp $lead;
my $rest = do { local $/; <DATA> };

for (my $i = 0; $i < length $lead; $i++ ) {
my $char = substr $lead, $i, 1;
next if $rest =~ /^.{$i}[^Q$charE]/m;
print "$i:$charn";
}


__DATA__
abcdefg
avcddeg
acbdeeg

回答№5の場合は0

配列要素を次のようにマークして、ファイルを1行ずつ読み取ることもできます。 undef 共通の一致がない行がある場合:

use strict;
use warnings;

open(my $read,"<","input_file") or die $!;

my $first=1; #Flag to indicate whether or not we are on the first line.
my @characters=(); #Array for characters

while(my $line=<$read>)
{
chomp($line);
if($first)
{
@characters=split(//,$line);
$first=0;
}
else
{
my @temp_arr=split(//,$line);

foreach(0..$#characters)
{
$characters[$_]=undef unless $characters[$_] eq $temp_arr[$_];
}
}

#If we do not have any characters in common, bail out!
unless(scalar(grep{defined($_)}@characters))
{
print "Sorry, there are no characters in common positions within all rows of file input_filen";
exit(1);
}
}

close($read);

print "Here are the common characters and positions:nn";

foreach(0..$#characters)
{
print "" . ($_ + 1) . ": " . $characters[$_] . "n" if defined($characters[$_]);
}

質問の入力の場合、出力は次のとおりです。

Here are the common characters and positions:

1: a
4: d
7: g

このコードは、すべての行の長さは同じです(または、少なくとも、最初の行より長い行はありません)。そうでない場合は、それに応じてコードを調整する必要があります。