修正したいファイルがあります。同じ問題のファイルが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の非破壊置換イディオムを使用して、入力を最初の(キー)列、中間列、および最後の(値)列に分割します。for
lines
S///
$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
答え2
簡単なAwkドア:
awk -v OFS='\t' '$3 == "total" {maxval[$1] = $5} $1 in maxval && $5 > maxval[$1] {$5 = maxval[$1]} {print}' input.txt
いくつかの改行を追加しました。
awk -v OFS='\t' '
$3 == "total" {
maxval[$1] = $5
}
$1 in maxval && $5 > maxval[$1] {
$5 = maxval[$1]
}
{print}' input.txt
説明する:
まず、入力ファイルの変数間隔に基づいて、元のテキストはタブ区切りのテキストであると仮定します。
デフォルトでは、Awkは隣接するタブまたはスペースの数に応じて別々のフィールドに解析します。このファイルには大丈夫です。
しかし、私たちは出力をきちんと整列させることを望み、デフォルトでいくつかのフィールド値を変更すると、Awkはその行のすべてのフィールド区切り文字を単一のスペースに変換します。したがって、出力フィールド区切り記号(OFS)をタブと同じに設定し、-v
変数を設定するフラグを使用します。
3番目のフィールドが文字列 "total"の行の場合、最大値を連想配列(最もよく知られているプログラミング言語に従って「ハッシュ」とも呼ばれる)に格納します。
行の最初のフィールドが連想配列に存在し、5番目のフィールドが大きいそのキーの最大値として、配列に格納されている値よりも現在の行の5番目のフィールドを変更します。
次に、変更するかどうかに関係なく現在の行を印刷します。
提供された入力への出力:
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