perl
ワンライナーの応答があるに違いないことはわかっていました。ここにあります-十分にテストされていないため、emptorに注意してください ;-)
perl -anE 'push @AoA,[@F]; $S{$_}++ for @F[0];}{for $i (0..$#AoA) {for $j (grep {$S{$_}==1} keys %S) {say "@{$AoA[$i]}" if @{$AoA[$i]}[0]==$j}}' data.txt
このアプローチの欠点は、わずかに変更された形式でデータを出力し (これは簡単に修正できると思います)、2 つのfor
ループと「バタフライ演算子」(!!) を使用することですgrep()
。 -つまり、自分でループをコーディングする必要がない場合でもコードが実行されるものです)。そのため、150 万レコードでは遅くなる可能性があります。awk
と比べて見てみたいですけどねuniq
。
プラス面では、モジュールを使用せず、Windows と OSX で実行する必要があります。これは、一意の最初の列を持つ類似のレコードが数十ある場合に機能し、一意の行をチェックする前に入力をソートする必要はありません。解決策は、Joseph Hall、Joh McAdams、およびbrian d foyによる『 Effective Perl Programming』の終わり近くにあるワンライナーの例からほとんど 引用されています(素晴らしい本です。スマート マッチとほこりが落ち着いたら、新しい版が登場することを願っています)。~~
given when
これがどのように機能するかです(私は思う):
- 使用し
-a
ているため、@F
配列を無料で取得できるため、分割する代わりにそれを使用します
- を使用し
-n
ているwhile() {}
ためループ内にいるためpush
、の要素は参照の無名配列として使用@F
されます ( は「無名配列コンストラクター」として機能します)。そうすれば、彼らはたむろし、後で参照できます(これは意味がありますか???)@AoA
[]
- 上記の本の
$seen{$_}++
イディオム ($S
代わりにを使用) を使用し、ここで @Axeman$seen
によって非常によく説明されているSOの一意の要素を調べ、要素を表示する回数に応じてハッシュのキーを設定/インクリメントします(または行) を与えられた値 (つまり、行の内容) に置き換えます。@F[0]
%S
- 「バタフライ」
}{
を使用してから抜け出しwhile
、別のブロックで、2 つのfor
ループを使用して外側の配列を調べ、各要素 (それ自体が無名配列$i
で、行ごとに 1 つ) を調べてから、内部の各無名配列を調べます。前に作成したハッシュ ( 、または内側のループ) で「1」に等しいgrep
値が含まれる配列で、これらの値を に連続して配置します。keys
%S
for $j (grep {$S{$_}==1} keys %S)
$j
- 最後に、外側の配列を繰り返し処理し、その配列の最初の要素が各 ( ) の値と等しい無名配列を出力します
$j
。( ) でそれを行います@{$AoA[$i]}[0]==$j
。
awk
@Kentの手にあるのはもう少し気の利いたものです。私の「回線ノイズ」を短縮または文書化する方法について誰かが提案を持っている場合 (そして、私は決してそれについては言いませんperl
!) 建設的なコメントを追加してください!
読んでくれてありがとう。