他の列の最大値に基づいて列値を変更するようにテキストファイルを処理します。

他の列の最大値に基づいて列値を変更するようにテキストファイルを処理します。

修正したいファイルがあります。同じ問題のファイルが100個あります。入力ファイルは次のとおりです

sample1 100A    total   1   1000
sample2 100A    total   1   5584
sample3 100A    total   1   8125
sample4 100A    total   1   59
                
sample1 .   year    1   1000
sample1 .   week1   20  1001
sample1 .   week2   50  1001
                
sample2 .   year    1   5584
sample2 .   week1   20  5585
sample2 .   week2   100 5585
                
sample3 .   year    1   8125
sample3 .   week1   55  8126
sample3 .   week2   100 8126
                
sample4 .   year    1   59
sample4 .   week1   10  59
sample4 .   week2   8   59

上記のファイルでは、3番目の列の「合計」はルックアップテーブルであり、最大値は以下の各サンプルの行を超えてはいけません。

たとえば、「sample1」の最大値は1000ですが、3列目の「week1」と「week2」の最大値は「1001」です。私はこれが「week1とweek2」の数行でのみ発生し、常に最大値より1万大きいことがわかりました。 「week1」および「week2」行の出力は、最大値「1000」に更新する必要があります。以下の出力例

sample1 100A    total   1   1000
sample2 100A    total   1   5584
sample3 100A    total   1   8125
sample4 100A    total   1   59
                
sample1 .   year    1   1000
sample1 .   week1   20  1000
sample1 .   week2   50  1000
                
sample2 .   year    1   5584
sample2 .   week1   20  5584
sample2 .   week2   100 5584
                
sample3 .   year    1   8125
sample3 .   week1   55  8125
sample3 .   week2   100 8125
                
sample4 .   year    1   59
sample4 .   week1   10  59
sample4 .   week2   8   59

どのように進むべきかについての指示を提供してください。私は学びたい初心者プログラマーです。ご協力ありがとうございます

ベストアンサー1

使用幸せ(以前のPerl_6)

~$ raku -e 'my @a = slurp.split("\n\n", 2);  print @a[0] ~ "\n\n"; 
            my %h;  for @a.[0].lines() { \%h.push: .words.[0,4] }; 
            for @a[1].lines {
                S/^ (\S+)(.* \s)(\S+) $/{"$0$1"}{ %h{$0} < $2 ?? "%h{$0}" !! "$2" }/.put };'   file.txt

RakuはPerlファミリーのプログラミング言語なので、構文は間違いなく「Perlに似ています」。上記では、slurpファイルを一度にメモリに入れ、2最初の段落の後にファイルをいくつかの部分に分割します。このデータは@a配列に保存されます。基準値()を含む最初の部分は@a[0]すぐに編集されますprint

%h次に、ハッシュ値を宣言します。 ...()を@a[0]使用して上のfor要約段落を繰り返しますlines。ここで、各行はスペースで区切られた行に分割され、最初wordsの/5番目の列は.[0,4]参照キー/値のペアとしてハッシュにpush追加されます。%h

ファイルの残りの部分()は@a[1]次のように繰り返されます。これは、ブロックの各行を分析/修正できることを意味します。変更された文字列を返すために、Rakuの非破壊置換イディオムを使用して、入力を最初の(キー)列、中間列、および最後の(値)列に分割します。forlinesS///$0$1$2

交換ではそのまま{"$0$1"}印刷します。ただし、最後の列の場合は、Rakuの三項演算子を使用して中括弧内でコードを実行できます。テスト ?? 本物 !! 間違ったこれより小さい場合は%h{$0}key関連項目)を返し、それ以外の場合は元の値()を返します。value$2$2

入力例:

sample1 100A    total   1   1000
sample2 100A    total   1   5584
sample3 100A    total   1   8125
sample4 100A    total   1   59

sample1 .   year    1   1000
sample1 .   week1   20  1001
sample1 .   week2   50  1001

sample2 .   year    1   5584
sample2 .   week1   20  5585
sample2 .   week2   100 5585

sample3 .   year    1   8125
sample3 .   week1   55  8126
sample3 .   week2   100 8126

sample4 .   year    1   59
sample4 .   week1   10  59
sample4 .   week2   8   59

出力例:

sample1 100A    total   1   1000
sample2 100A    total   1   5584
sample3 100A    total   1   8125
sample4 100A    total   1   59

sample1 .   year    1   1000
sample1 .   week1   20  1000
sample1 .   week2   50  1000

sample2 .   year    1   5584
sample2 .   week1   20  5584
sample2 .   week2   100 5584

sample3 .   year    1   8125
sample3 .   week1   55  8125
sample3 .   week2   100 8125

sample4 .   year    1   59
sample4 .   week1   10  59
sample4 .   week2   8   59

最後に、中間データ構造を見ることが役に立つことが多いので、%hハッシュは次のようになります(used .say for %h.sort;)。

sample1 => 1000
sample2 => 5584
sample3 => 8125
sample4 => 59

https://docs.raku.org/syntax/S%2F%2F%2F%20Non-destructive%20replacement
https://docs.raku.org/言語/operators#infix_??_!
https://docs.raku.org/言語/regexes
https://raku.org

おすすめ記事