ishiducaの日記 このページをアンテナに追加 RSSフィード

2009-10-25

[][][]tsvファイルの読み書き 12:12 tsvファイルの読み書き - ishiducaの日記 を含むブックマーク はてなブックマーク - tsvファイルの読み書き - ishiducaの日記 tsvファイルの読み書き - ishiducaの日記 のブックマークコメント

タブ(\t)区切りのファイルを読み込んで、ごにょごにょ。そんでもって書き出す。 という処理をおこなうのに2次元配列に変換しておくと都合がいいので、

  • 読み込んで、2次元配列に変換するサブルーチン
  • 2次元配列をタブ区切りのデータに直して書き込むサブルーチン

sample.tsv(便宜上スペース区切り)

初めてのPerl     3600  O'REILY
続・初めてのPerl 3200  O'REILY
BLOG HACKS       2900  O'REILY
ミニマルPerl     4200  O'REILY

file.pl

sub load{
    my $file = shift;
    -e $file or die qq(not found "$file");
    my @data;
    open my $fh, "<", $file or die qq(can not open "$file");
    eval{ flock($fh,2); };
    while( <$fh> ){
        chomp;
        my @cells = split /\t/;
        push @data, \@cells;
    }
    close $fh;
    @data;
}

sub save{
    my $file = shift;
    -e $file or warn qq(not found "$file");
    my @data;
    foreach my $cell ( @_ ){
        my $str = join "\t", @{$cell};
        push @data, "$str\n";
    }
    open my $fh, ">", $file or die qq(can not open "$file");
    eval{ flock($fh,2); };
    print $fh @data;
    close $fh;
    "saved";
}

1;

上記のサブルーチンを使って金額の安い順に並び替えたリストにして書き込む

sort.pl

#!/usr/bin/perl
use strict;
use warnings;
require 'file.pl';

my @data = &load( 'sample.tsv' );
@data = sort{ $a->[1] <=> $b->[1] }@data;

print &save( 'sort_sample.tsv', @data );

exit 0;

実行

$ perl sort.pl

結果

saved

実際にファイルの中身を見てみます。

$ cat sort_sample.tsv

出力

BLOG HACKS       2900    O'REILY
続・初めてのPerl 3200    O'REILY
初めてのPerl     3600    O'REILY
ミニマルPerl     4200    O'REILY

CamiCami2011/06/05 12:20In awe of that awnser! Really cool!

hunwfqphunwfqp2011/06/05 17:367k0Pk9 <a href="http://jabwchslvcyp.com/">jabwchslvcyp</a>

gsqsmtgsqsmt2011/06/06 22:49uwYLQj , [url=http://nskgeykqazeg.com/]nskgeykqazeg[/url], [link=http://miivgnmhdygt.com/]miivgnmhdygt[/link], http://luhgyhzekwvn.com/

qjokekbsqjokekbs2011/06/07 17:45dzx81q <a href="http://gteiwjmusklf.com/">gteiwjmusklf</a>

zghleumzghleum2011/06/09 19:17Lfux4H , [url=http://tcdptdmvajwt.com/]tcdptdmvajwt[/url], [link=http://refdedletyjd.com/]refdedletyjd[/link], http://uxobwcousuoa.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20091025

2009-03-06

[][]文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた 14:14 文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた - ishiducaの日記 を含むブックマーク はてなブックマーク - 文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた - ishiducaの日記 文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた - ishiducaの日記 のブックマークコメント

$ perl -wl -e '$,="\n";print sort { length $a <=> length $b } split / /, "a pretty dog in the zoo.";'

a
in
dog
the
zoo.
pretty

ブロック内の評価は -1, 0, 1 のいずれかでいいので、こんなのも(まったく意味ないけど)。

$ perl -wl -e '$,="\n"; print sort { (($a*$b) % 3) - 1 } qw/12 10 45 9 11/;'

とすると

12
11
45
10
9

DonteDonte2011/10/08 17:37Dude, right on there borther.

owomyhowomyh2011/10/08 23:241jlJUU <a href="http://ssdikerzdfny.com/">ssdikerzdfny</a>

bxuxbwrbxuxbwr2011/10/10 19:159oAIQb , [url=http://gjdtmmddkmtd.com/]gjdtmmddkmtd[/url], [link=http://xjqbheyhkkdd.com/]xjqbheyhkkdd[/link], http://hntcbromdugl.com/

yaqwzfpkmxsyaqwzfpkmxs2011/10/11 23:49LYae8m <a href="http://rbvrcmytrhaj.com/">rbvrcmytrhaj</a>

xfmacwjxfmacwj2011/10/13 02:03Kla4tm , [url=http://lvcbuverbmqj.com/]lvcbuverbmqj[/url], [link=http://vvayhhsypbtt.com/]vvayhhsypbtt[/link], http://izaaobutpyjh.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20090306

2009-03-01

[][]大文字小文字の違いを無視した並び替え 19:00 大文字小文字の違いを無視した並び替え - ishiducaの日記 を含むブックマーク はてなブックマーク - 大文字小文字の違いを無視した並び替え - ishiducaの日記 大文字小文字の違いを無視した並び替え - ishiducaの日記 のブックマークコメント

メモ。

@F = sort { "\L$a" cmp "\L$b" } @F; # 大文字と小文字を区別しないソート

「ミニマルPerl」P.223 - "sortの利用上のヒント" を参照


追記 2009.03.06

id:Cress さんからコメントいただいた(ありがとうございます)ので、ちょっと書き足します。

最初の例では、比較する $a と $b を \L オプションで 小文字に統一して cmp で比較していますが、大文字に統一して比較してもいいわけですから \U を使うのもOKと。

@F = sort { "\U$a" cmp "\U$b" } @F;

さて

...ここで、大文字小文字変換の影響が、比較に使われるダブルクォートの中の文字列に限定される点に注目してください。最終的に sort が返す文字列に影響しないのです。...

とあるのですが(「ミニマルPerl」P.223)、僕はメカニズムがよくわかっていません。どなたか詳しく説明されている文献があれば、教えていただきたいところですが、自分なりに解釈してみると、「ブロック内の $a と $b は ブロック外(右)の @F で比較する要素が代入される特殊な変数」ということでいいのかしらん?

例えば $a と $b を使わずに、適当な変数( $before $after )を使ってみる

$ perl -wl -e '$,="\n";print sort { $before cmp $after } split / /, "a pretty dog in the zoo.";'

とすると

Name "main::before" used only once: possible typo at -e line 1.
Name "main::after" used only once: possible typo at -e line 1.
Use of uninitialized value in string comparison (cmp) at -e line 1.

と怒られます。sort関数で、ブロック内の比較に使う変数は $a と $b だけっぽいです。デフォルトなだけかも知れませんけど。 また、順番ですが $a が前の値、$b がその次の値っぽいですね

$ perl -wl -e '$,="\n";print srot { $a cmp $b } split / /, "a pretty dog in the zoo.";'

a
dog
in
pretty
the
zoo.

となりますが、

$ perl -wl -e '$,="\n";print sort { $b cmp $a } split / /, "a pretty dog in the zoo.";'

zoo.
the
pretty
in
dog
a

となりました。

$ perl -wl -e '$,="\n";print reverse sort { $a cmp $b } split / /, "a pretty dog in the zoo.";'

と同じ結果です。

sort のメカニズムは重点的に理解しておきたいところですね。

CressCress2009/03/05 17:36@F = sort { lc($a) cmp lc($b) } @F;
とか……意味は一緒なんですが。
perldoc -f lc すると、"\L"に関しても書かれていますね。
当然ですが、"\U"でも行けそうです。

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20090301