各行ペアの情報を1行にまとめるにはどうすればよいですか?

各行ペアの情報を1行にまとめるにはどうすればよいですか?

次のデータがあります(実際のデータには50,000桁と8000行を超える)。

入力する:

1 11122
1 21121
2 22221
2 11122
3 21121
3 11122

同じ名前の最初の行の値の横に2番目の行の値を配置したいと思います。また、各値ペア間の区切り文字としては2つのスペースが必要であり、異なる値ペア間の区切り記号としてタブが必要です。出力は次のようになります。

出力:

1   1  2    1  1    1  1    2  2    2  1
2   2  1    2  1    2  1    2  2    1  2
3   2  1    1  1    1  1    2  2    1  2

どんな提案がありますか?

答え1

私はPerlを使い、次のようにonelinerとして実行します。

perl -wne 'sub parseline { ($id,$v) = split; return split //,$v };
    @a = parseline();
    print "$id\t";
    $_ = <>;
    @b = parseline();
    for ($i=0; $i<@a; $i++) {
      print "$a[$i]  $b[$i]\t"
    };
    print "\n"' < input  > output

説明する:

  • perl -wne各入力行に対して残りのコマンドを実行します。
  • sub parseline { .... }入力を解析し、行の最初の数字を設定$idし、残りは文字配列として返します。
  • @a=parseline()文字の最初の行は @a 配列に格納されます。
  • 次に印刷$idしてTAB(\t)を押します。
  • $_=<>; @b=parseline();次の(偶数)行を読み、そのデータを配列に入れます。@b
  • for ($i=0; $i<@a; $i++) { print "$a[$i] $b[$i]\t" }配列の各要素に対して、@a要素、2つのスペース、配列の対応する要素を印刷してから、タブを@b印刷します。
  • print "\n"最後に改行文字を印刷します
  • at startパラメーターのため、-nプロセス全体は3行、5行、7行の順に始まります。perl
  • < input > output入力を読み取るファイルと出力を書き込むファイルを示します。

注:コードは各行の末尾に追加のタブを印刷します。クラウドソーシングを防ぎ、コードをより簡単に保つための読者の練習でこれを削除しました。また、コードでは、ペアの行が常に2つの行が順番に連続していると想定しています(例を参照)。

入力ファイルを1行ずつ処理するため、数千行にわたって簡単に線形に拡張できます。

答え2

pairwiseこれは、モジュールの関数を使用して2つの配列をList:MoreUtils連結し、IDが一致する行(最初のフィールド)が連続行にある必要がないMatija Nalisのスクリプトバージョンです。つまり、複数行に分けることができます。

#! /usr/bin/perl

use strict;
use warnings;
use List::MoreUtils qw(pairwise);

sub parseline { my ($id,$v) = split; return $id, split //,$v };

my %ID=();

while (<>) {
    my ($id, @line) = parseline();

    if ( !defined($ID{$id}) ) {
      push @{ $ID{$id} }, @line ;
    } else {
      my @paired = pairwise { "$a  $b" } @{ $ID{$id} }, @line;
      print join("\t", $id, @paired), "\n";
      delete $ID{$id};
    };
};

$idMNのparselineサブルーチンは、グローバル変数を使用するのではなく、各行のIDと要素の配列を返すように変更されました。

$id%ID解析された各行のハッシュを格納するためのキーとして使用されます。与えられたものを最初に見るとき、解析された行配列()をハッシュに$id保存し、次の行に移動します。@line次に見ると、保存した配列を現在の配列@lineとペアで連結し、TABフィールド区切り文字を使用して印刷してからハッシュから$id削除%IDします。

man List::MoreUtilsこの機能のしくみのpairwise詳細については、リソースを参照してください。ちなみに、List::UtilさまざまList::MoreUtilsなリスト(配列とも呼ばれます)を実行するための2つの素晴らしいモジュールです。

出力:

$ ./zara.pl zara.txt  
1   1  2    1  1    1  1    2  2    2  1
2   2  1    2  1    2  1    2  2    1  2
3   2  1    1  1    1  1    2  2    1  2

関連情報