ペアの項目を表示する2つの列を持つタブ区切りファイルがありますpairs.tsv
。 2つの列の2つの値に基づいて3番目の列を作成し、アイテムにグループを割り当てようとしています。
ただし、場合によっては、複数の項目が同じグループに属します。したがって、スクリプトは行1から始めてgroup01
最初のペアに割り当て、残りの行で列1または列2の2つの値のいずれかが発生することを確認し、trueの場合はそのgroup01
行にも割り当てる必要があります。
繰り返し検索でペア付きファイルのすべての項目がgroup01
割り当てられるまで、この手順を繰り返す必要がありますgroup01
。
その後、スクリプトは次の行に進み、まだ割り当てられていない場合はグループをグループに割り当て、group02
行2の列1または2の項目が下の行に表示されたら、残りのファイルを再確認する必要があります。もしそうなら、それを割り当ててくださいgroup02
。その行をください。など。
pairs.tsv
:
a b
c d
e f
e g
h i
h j
k l
f g
m n
i j
出力ファイルは次のようにする必要があります。
a b group01
c d group02
e f group03
e g group03
h i group04
h j group04
k l group05
f g group03
m n group06
i j group04
ベストアンサー1
これはファイルを入力して一度だけ行うことができます。
awk -F'\t' '{
# "groups" is an associative array containing the group numbers
# for the values in fields $1 and $2.
if (! ($1 in groups)) {
# "gc" stands for "group counter"
groups[$1] = ++gc;
}
groups[$2] = groups[$1]
printf "%s\t%s\tgroup%02i\n", $1, $2, groups[$1];
}' pairs.tsv
a b group01
c d group02
e f group03
e g group03
h i group04
h j group04
k l group05
f g group03
m n group06
i j group04
%groups
私はまた、awkバージョンのようにハッシュ(連想配列)を使用するPerlバージョンを作成しました。そして@pairs
各グループのペアを維持するには、配列の配列配列(AoA - つまり、各要素が別の配列の配列)を呼び出します。結果を読み取ったとおりに印刷するのではなく、読み取った後にすべての入力を印刷します。
#!/usr/bin/perl
use strict;
my $gc = 1; # group counter
my %groups; # hash containing group numbers for each element
my @pairs; # array of arrays containing pairs
while(<>) {
chomp;
my ($a,$b) = split /\t/;
$groups{$a} = $gc++ unless (defined($groups{$a}));
$groups{$b} = $groups{$a};
push @{ $pairs[$groups{$a}] }, [ $a, $b ];
};
END {
for my $g (keys @pairs) {
for my $p (@{ $pairs[$g] }) {
printf "%s\t%s\tgroup%02i\n", @$p[0], @$p[1], $g;
}
};
}
@pairs 配列を繰り返すので、出力はグループ番号に基づいてソートされます。
$ ./group.pl pairs.tsv
a b group01
c d group02
e f group03
e g group03
f g group03
h i group04
h j group04
i j group04
k l group05
m n group06
ソートを除いて、両方のバージョンの出力は同じです。