0

まだ perl プログラミングに問題があり、スクリプトを機能させるためにプッシュする必要があります。2 つのファイルがあり、リスト ファイルを使用してデータ ファイルから行を「抽出」したいと考えています。問題は、リスト ファイルが次のようにフォーマットされていることです。

X1 A B
X2 C D
X3 E F

そして、私のデータは次のようになります。

A X1 2 5
B X1 3 7
C X2 1 4
D X2 1 5

データ ファイル内の行を選択するために、リスト ファイルから要素のペアを取得する必要があります。同時に、次のような出力を書きたいと思います。

X1 A B 2 5 3 7
X2 C D 1 4 1 5

perl コードを書こうとしていますが、何か役に立つものを作成できません。私はこの時点で:

open (LIST, "< $fils_list") || die "impossibile open the list";
@list = <LIST>;
close (LIST);
open (HAN, "< $data") || die "Impossible open data";
@r = <HAN>;
close (HAN);
for ($p=0; $p<=$#list; $p++){
chomp ($list[$p]);
($x, $id1, $id2) = split (/\t/, $list[$p]);
$pair_one = $id1."\t".$x;
$pair_two = $id2."\t".$x;

for ($i=0; $i<=$#r; $i++){
chomp ($r[$i]);
($a, $b, $value1, $value2) = split (/\t/, $r[$i]);
$bench = $a."\t".$b;

if (($pair_one eq $bench) || ($pair_two eq $bench)){
print "I don't know what does this script must print!\n";
}
}
}

何を印刷するかについて合理化できません。どんな提案でも大歓迎です!

4

2 に答える 2

2

いくつかの一般的な推奨事項:

  • コードをインデントして、プログラムの構造を示します。
  • $aorではなく、意味のある変数名を使用してください$value1(以下でそうする場合、これは私のドメイン知識の不足によるものです)。
  • プログラムに適したデータ構造を使用してください。
  • 行を解析するような操作を複数回実行しないでください。
  • Perl では、すべてのプログラムはuse strict; use warnings;.
  • use autodie自動エラー処理用。

また、このopenような関数を使用するopen my $fh, "<", $filenameと安全です。

データ構造について私が言ったことを覚えていますか? 2 番目のファイルには、次のようなエントリがあります。

A X1 2 5

これは、2 次キー、1 次キー、およびいくつかのデータ列のように見えます。キーと値の関係は、ハッシュ テーブルを使用して表現するのが最適です。

use strict; use warnings; use autodie;
use feature 'say'; # available since 5.010

open my $data_fh, "<", $data;
my %data;
while (<$data_fh>) {
  chomp; # remove newlines
  my ($id2, $id1, @data) = split /\t/;
  $data{$id1}{$id2} = \@data;
}

%dataこれで、簡単なルックアップに使用できるネストされたハッシュが作成されました。

open my $list_fh, "<", $fils_list;
LINE: while(<$list_fh>) {
  chomp;
  my ($id1, @id2s) = split /\t/;
  my $data_id1 = $data{$id1};
  defined $data_id1 or next LINE;  # maybe there isn't anything here. Then skip

  my @values = map @{ $data_id1->{$_} }, @id2s;  # map the 2nd level ids to their values and flatten the list

  # now print everything out:
  say join "\t", $id1, @id2s, @values;
}

このmap関数は foreach ループに少し似ており、値のリストを作成します。@{ ... }データ構造は配列を保持するのではなく、配列への参照を保持するため、here が必要です。は逆参照演算子@{ ... }です。

于 2013-08-08T16:07:41.120 に答える
1

これは、主にハッシュ resp を使用して行う方法です。ハッシュ参照と配列参照 (test1.txt と test2.txt には、例で提供したデータが含まれています):

use strict;
use warnings;

open(my $f1, '<','test1.txt') or die "Cannot open file1: $!\n";
open(my $f2, '<','test2.txt') or die "Cannot open file2: $!\n";

my @data1 = <$f1>;
my @data2 = <$f2>;

close($f1);
close($f2);

chomp @data1;
chomp @data2;

my %result;

foreach my $line1 (@data1) {
    my @fields1 = split(' ',$line1);
    $result{$fields1[0]}->{$fields1[1]} = [];
    $result{$fields1[0]}->{$fields1[2]} = [];
}

foreach my $line2 (@data2){
    my @fields2 = split(' ',$line2);
    push @{$result{$fields2[1]}->{$fields2[0]}}, $fields2[2];
    push @{$result{$fields2[1]}->{$fields2[0]}}, $fields2[3];
}

foreach my $res (sort keys %result){
    foreach (sort keys %{$result{$res}}){
        print $res . " " . $_ . " " .  join (" ", sort @{$result{$res}->{$_}}) . "\n";
    }
}
于 2013-08-08T16:18:27.280 に答える