テキスト操作 - 値に基づいて列を行に置き換えます。

テキスト操作 - 値に基づいて列を行に置き換えます。

次の内容を含むCSVファイルのテキストを操作するコードを書きたいです。

71w - Rus,51200
71w - Phi,307200
71w - Ukr,307200
71w - Ukr,51200
71w - Mic,102400
71w - Mic,51200
71w - Jul,256000
71w - Jul,51200
71w - Pro,256000
71w - Uni,51200
71w - Ind,50176
71w - Ind,40960
71w - Sin,358400
71w - May,20480
71w - Tha,512000
71w - Tha,972800
71w - Bar,1280000
71w - Bar,102400
71w - Bar,2048000
71w - Upg,358400
71w - Leg,20480
71w - Res,153600

同じ値を持つ列を収集して、次のようにその行に配置したいと思います。

71w - Rus,51200
71w - Phi,307200
71w - Ukr,307200,51200
71w - Mic,102400,51200
71w - Jul,256000,51200
71w - Pro,256000
71w - Uni,51200
71w - Ind,50176,40960
71w - Sin,358400
71w - May,20480
71w - Tha,512000,972800
71w - Bar,1280000,102400,2048000
71w - Upg,358400
71w - Leg,20480
71w - Res,153600

ありがとうございます。

ベストアンサー1

これを行う良い方法は、連想配列またはハッシュを使用することです。各ハッシュのキーは最初のフィールドであり(より良い用語を使用するために「ids」と呼びます)、各キーに格納されている値はカンマ区切り値を含む文字列です。 ID リストまたは次を含む配列です。同じ内容。

奇妙な:

この awk バージョンは、配列の連想配列を扱うよりも (awk で) 簡単なので、カンマ区切り文字列を使用します。

#!/usr/bin/awk -f

BEGIN {
  FS=" *, *";
  OFS="";
}

{
  key=$1; $1=""; $0=$0;

  if (length(ids[key]) > 0) {
    ids[key]=ids[key]","$0;
   } else {
    ids[key] = $0
   };
}

END {
  for (k in ids) {
    print k "," ids[k]
  }
}

Perlの配列ハッシュ(または「HoA」)操作は、文字列を連結するよりも難しくありません(そしてより便利で柔軟です)。

#!/usr/bin/perl -w

use strict;

my %ids = ();

while(<>) {
  chomp;
  my @F = split /\s*,\s*/;
  push @{ $ids{$F[0]} }, $F[1];
};


END {
  foreach my $key (keys %ids) {
    print $key . ',' .  join(",",@{ $ids{$key} }), "\n";
  }
}

awk および perl バージョンの出力は同じです。

71w - Ukr,307200,51200
71w - Bar,1280000,102400,2048000
71w - Res,153600
71w - Upg,358400
71w - Sin,358400
71w - Mic,102400,51200
71w - May,20480
71w - Tha,512000,972800
71w - Jul,256000,51200
71w - Uni,51200
71w - Ind,50176,40960
71w - Pro,256000
71w - Rus,51200
71w - Leg,20480
71w - Phi,307200

注:awkおよびperlバージョンの出力は特別な順序ではなく、実行されるたびに異なる順序で表示されることがあります。これは、awkの「連想配列」とPerlの「ハッシュ」(同じものを指す2つの名前)が本質的に順序がないためです。

sort必要に応じて出力をパイプできます。または、Perlでは次のものを使用できます。

      foreach my $key (sort keys %ids) {

変える:

      foreach my $key (keys %ids) {

また、各IDの個々の値を配列に格納するため、Perlでも値を簡単に並べ替えることができます。たとえば、ENDPerlバージョンのブロック全体を次のように置き換えます。

END {
  foreach my $key (sort keys %ids) {
    print $key . ',' .  join(",",sort @{ $ids{$key} }), "\n";
  }
}

出力は次のとおりです。

71w - Bar,102400,1280000,2048000
71w - Ind,40960,50176
71w - Jul,256000,51200
71w - Leg,20480
71w - May,20480
71w - Mic,102400,51200
71w - Phi,307200
71w - Pro,256000
71w - Res,153600
71w - Rus,51200
71w - Sin,358400
71w - Tha,512000,972800
71w - Ukr,307200,51200
71w - Uni,51200
71w - Upg,358400

おすすめ記事