■Windows版Perlの細道・けもの道

■ナビゲータ

[南北館(最初のメニュー)]

  1. [Windows版Perlの細道・けもの道]
    1. [1.準備編]
    2. [2.基本編]
      1. [2-1.基本処理]
      2. [2-2.キーブレイク処理]
      3. [2-3.マッチング(照合)処理]
      4. [2-4.ソート(並べ替え)処理]
        1. [2-4-1.レコード全体のソート(並べ替え)]
        2. [2-4-2.CSVファイルの文字列型昇順ソート(並べ替え)]
        3. [2-4-3.CSVファイルの文字列型・数値型/昇順・降順ソート(その1)]
        4. [2-4-4.CSVファイルの文字列型・数値型/昇順・降順ソート(その2)]
        5. [2-4-5.大量のCSVファイルのソート(並べ替え)する場合の考慮事項]
        6. [2-4-6.大量のCSVファイルの文字列型/昇順ソート(並べ替え)]
        7. [2-4-7.大量のCSVファイルの文字列型・数値型/昇順・降順ソート(並べ替え)]
      5. [2-5.パターンマッチ処理]
    3. [3.応用編]
    4. [スクリプトと入力データのサンプル]
rubyではどう処理する?
同じことをrubyではこうしています。

2.基本編

2-4.ソート(並べ替え)処理

2-4-5.大量のCSVファイルのソート(並べ替え)する場合の考慮事項

大量のCSVファイルのデータをソート(sort:並べ替え)するのは、本来はデータベース側で行うことであって、Perlで行うことではありません。しかし、実際にはPerlで行うことになる場合もあります。そうした場合にPerlでどのような対応を行うかについて説明していきます。ここで大量のCSVファイルとは、[2-4-2.CSVファイルの文字列型昇順ソート]で並べ替える場合は100万件以上、[2-4-3.CSVファイルの文字列型・数値型/昇順・降順ソート(その1)]で並べ替える場合は10万件以上のCSVデータが1つのファイルに入っていることを前提にしています。これ以上のデータを並べ替える(ソートする)には以下の手順で行います。

まず、並べ替えの方式のどれかを確認します。

  1. すべての並べ替え(ソート)のキーが文字列型の昇順である場合
  2. 並べ替え(ソート)のキーが文字列型の降順または数値型の昇順や降順を含む場合

1の場合は、以下の手順で行います。

    1. まず、下記に示すスクリプトでソート(並べ替え)キーごとの件数と累計件数が出ますので、データが100万件程度ずつになるような適切なソート(並べ替え)キーを探します(100万件を大幅に超える件数でソート(並べ替え)キーが同じ場合は、ソート(並べ替え)せずにそのまま出力するようにします)。
    2. 次に、[2-4-6.大量のCSVファイルの文字列型/昇順ソート]を参考にデータの並べ替えを行います。
    3. 上記の場合ソート(並べ替え)できる件数は1000万件から1500万件程度までです(PCの性能によって異なりますが、Windows7 Professionalでメモリ8GBのときで約2分強かかります。どの程度の件数が適切かは各自のPCのOSやメモリ等によって異なりますので、各自のPCで確認してから実行してください。また、他のアプリケーションの起動は極力避け、タスクマネージャーでCPUやメモリ、ディスクの状況などを確認しながら実行してください)。それ以上であれば、[2-4-6.大量のCSVファイルの文字列型/昇順ソート]のスクリプトを2つ以上作成した後、[3-3-2.複数のファイルをまとめて、1つのファイルに出力する]で1つのファイルにまとめます。

2の場合は、以下の手順で行います。

    1. まず、下記に示すスクリプトでソート(並べ替え)キーごとの件数件数と累計件数が出ますので、データが10万件程度ずつになるような適切なソート(並べ替え)キーを探します。(10万件を大幅に超える件数でソート(並べ替え)キーが同じ場合は、ソートせずにそのまま出力するようにします)。
    2. 次に、[2-4-7.大量のCSVファイルの文字列型・数値型/昇順・降順ソート]を参考にデータの並べ替えを行います。
    3. 上記の場合ソート(並べ替え)できる件数は100万件から150万件程度までです(PCの性能によって異なりますが、Windows7 Professionalでメモリ8GBのときで約2分強かかります。どの程度の件数が適切かは各自のPCのOSやメモリ等によって異なりますので、各自のPCで確認してから実行してください。また、他のアプリケーションの起動は極力避け、タスクマネージャーでCPUやメモリ、ディスクの状況などを確認しながら実行してください)。それ以上であれば、[2-4-7.大量のCSVファイルの文字列型・数値型/昇順・降順ソート]のスクリプトを2つ以上作成した後、[3-3-2.複数のファイルをまとめて、1つのファイルに出力する]で1つのファイルにまとめます。

実際に応用する場合は、入出力データのファイル名を変更し、「@sortkey = (0)」の部分を変更します。この例では、1番目の項目を第1キーとして並べ替えるように指定しています。Perlでは、配列のインデックスは「0」から開始されますので、1番目の項目を「0」、2番目の項目を「1」として指定することに注意してください。

下記の例では、フィールドを「"」(ダブルクォーテーションつき)で囲み、それぞれのデータを「,」(カンマ)で区切っている形式を前提としているため、

    $tmp    =   $line1;
    $tmp    =~  s/(?:\x0D\x0A|[\x0D\x0A])?$/,/; 
    @in1    =   map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_}   
                ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);  
   

としていますが、フィールドを「"」(ダブルクォーテーションつき)で囲まずに、それぞれのデータを「,」(カンマ)で区切っている、いわゆる「CSV2形式」であれば、以下のようにすることができます。

    @in1    =   split(",",$line1,-1);
   

また、タブ区切りであれば、以下のようにすることができます。

    @in1    =   split("\t",$line1,-1);
   
【スクリプト】
# keycount.pl   
# 内容 :CSV形式のファイルのソート(並べ替え)キーごとの
#       件数と累計件数をカウントする。
# Copyright (c) 2011 Mitsuo Minagawa, All rights reserved.
# (minagawa@fb3.so-net.ne.jp)  
# 使用方法 : c:\>perl keycount.pl   
#   
open(IN1,"input.txt");  
open(OUT1,">output.txt");   

# ソート(並べ替え)キーの入っている項目番号    
@sortkey        =   (0);  
# ソート(並べ替え)用のキー    
$key            =   undef;  
# ソート(並べ替え)用のキーと件数をセットするハッシュ  
%sort_record    =   (); 
# 累計件数  
$total_ctr  =   0;  
# ソート(並べ替え)キーとなる項目番号から
# ソート(並べ替え)キーとなる文字列を作っておく    
while   ($line1 =   <IN1>)  {   
    # 対象ファイルをカンマで分解する    
    chomp($line1);  
    $tmp    =   $line1;     
    $tmp    =~  s/(?:\x0D\x0A|[\x0D\x0A])?$/,/; 
    @in1    =   map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_}   
               ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);   
#   @in1    =   split("\t",$line1,-1);  
    # ソート(並べ替え)キーとなる項目内容をタブをはさんで連結してキーとする    
    foreach $sortno (@sortkey)  {   
        $key    .=  $in1[$sortno] . "\t";   
    }   
    chop($key); 
    # ソート(並べ替え)キーに該当するキーがあれば、件数を加算する。    
    if      ($sort_record{$key})            {   
            $sort_record{$key}  +=  1;  
    }   
    # 新たなソート(並べ替え)キーに該当する場合は、初期値1をセットする。   
    else                                    {   
            $sort_record{$key}  =   1;  
    }   
    $key    =   undef;  
}   
# ハッシュのキーをソート(並べ替え)し、キー順にレコードを出力する  
foreach $recno  (sort   keys    %sort_record)   {   
        $total_ctr  +=  $sort_record{$recno};   
        $out1   =   join("\t",$recno,$sort_record{$recno},$total_ctr);  
        print OUT1 "$out1\n";   
}   
close(IN1); 
close(OUT1);    
   


【スクリプトとデータのサンプル】

スクリプトはこちらにあります。

入力データのサンプルはこちらにあります。

【入力データ】
ccc,5555   
aaa,7777
bbb,9999
aaa,1111
bbb,3333
bbb,4444
aaa,5555
ccc,1111
   


【出力データ:ソート(並べ替え)キーごとの件数と累計件数】
aaa 3   3
bbb 3   6
ccc 2   8
   


Copyright (c) 2011-2013 Mitsuo Minagawa, All rights reserved.