2006/5/20形式、複数フィールドのソート

このQ&Aのポイント
  • 質問文章で提供されたデータを第1フィールド、第2フィールド(年月日)、第3フィールドの順でソートする方法について教えてください。
  • 質問文章で述べられているように、2006/05/20形式で保存されているデータをソートするには、年月日を分解する必要があります。
  • 2006/5/20形式のソートを行う際には、特定のフィールドをもとにソートする方法を使用し、複数フィールドのソートも組み合わせて実行する必要があります。
回答を見る
  • ベストアンサー

2006/5/20形式、複数フィールドのソート

↓のような感じでデータが入っているとします。 @hogehoge = [ 1020,2006/5/13,B 1020,2006/5/1,B 1020,2006/5/1,C 1020,2006/5/13,E 1023,2006/5/2,D 1020,2006/5/20,D 1023,2006/5/7,C 1020,2006/5/9,E 1022,2006/5/9,D }; これを第1フィールド、第2フィールド(年月日)、第3フィールドの順でソートしたいのですが、具体的にどのようにやればよいのでしょうか? 一番困る点が、2006/05/20形式で保存してあるという 点です。これはやはり分解しないとソートできない のでしょうか?そうなると複雑になります。 http://www.din.or.jp/~ohzaki/perl.htm#SortST は見て試しに作ったのですが、うまくソートされません。 データがそのまま保存されています。 上のURLにある文章を読んだので、特定のフィールドを もとにソートする方法は大体わかりましたが、複数フィー ルドのソートや2006/05/20形式のソートもまじってくる のでわからなくなります。 @hogehoge = [ 1020,2006/5/1,B 1020,2006/5/1,C 1020,2006/5/9,E 1020,2006/5/13,E 1020,2006/5/13,B 1020,2006/5/20,D 1022,2006/5/9,D 1023,2006/5/2,D 1023,2006/5/7,C }; こんな感じでソートさせて保存(書き込み)したいので すが、ご教授よろしくお願いします。

  • Perl
  • 回答数3
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

えーと、 #1のスクリプトの末尾に for my $item (@sorted_table) { printf "ID1:%d, Date:%s, ID2:%s\n", $item->[0], $item->[1], $item->[2]; } というのを追加して結果を以下のように出力してみましたが、 ID1:1020, Date:2006/5/1, ID2:B ID1:1020, Date:2006/5/1, ID2:C ID1:1020, Date:2006/5/9, ID2:E ID1:1020, Date:2006/5/13, ID2:B ID1:1020, Date:2006/5/13, ID2:E ID1:1020, Date:2006/5/20, ID2:D ID1:1022, Date:2006/5/9, ID2:D ID1:1023, Date:2006/5/2, ID2:D ID1:1023, Date:2006/5/7, ID2:C ID1が同じときには日付を使ってソートしていて、きちんと 5/9が5/13や5/20よりも前に来ているのですが、どのようなデータで どうなったのでしょうか? [1][2]のような書き方は、リスト(配列)の要素にリストが来ているときの 入れ子になったほうのリストの要素へアクセスするときに使います。 詳しくは参考URLをどうぞ。

参考URL:
http://www.kt.rim.or.jp/%7Ekbk/perl5.005/perllol.html

その他の回答 (2)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

すみません。バグってました。 $a->[1][2] <=> $b->[1][1] # 第2フィールドで比較 日 は $a->[1][2] <=> $b->[1][2] # 第2フィールドで比較 日 の間違いです($bの後のカッコの添え字が違う)。 比較が間違っているのでソート結果もおかしくなってますね。 それと、 (split(/\,/,$a))[1] cmp (split(/\,/,$b))[1] の件ですが、これだとフィールドを文字列として比較してしまうので、 '9' が '12' より大きくなってしまいます。'09'だと正しく並ぶのは 文字列比較しても'09'は'12'より小さくなるからです。cmpは文字列として 比較、<=>は数値として比較を行う演算子ですので選択するときは気をつけてください。

ma_trix
質問者

お礼

早速の訂正ありがとうございます。 そちらのバグには即座に気づいたので訂正し、トライしてみましたが第2フィールドがソートされません。 [1][2] の書き方はWEB、本にも載っていなく、現在調べておりますが、そういう書き方があるのですね。 また、本屋行って調べてみますが、いいヒントがあればまた教えてください。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

@hogehoge が ( [1020, '2006/5/1', 'B'], [1020, '2006/5/1', 'C'], ... ); というフォーマットの間違いであるなら、以下のようにしてできます。 日付が05/01のようになっていなかったので、分割しています。 もし0が補完されているなら、分割せずに文字列比較で済ませることもできます。 use strict; use warnings; # use Data::Dumper; デバッグ用 my @table = ( [1020, '2006/5/13', 'B'], [1020, '2006/5/1', 'B'], [1020, '2006/5/1', 'C'], [1020, '2006/5/13', 'E'], [1023, '2006/5/2', 'D'], [1020, '2006/5/20', 'D'], [1023, '2006/5/7', 'C'], [1020, '2006/5/9', 'E'], [1022, '2006/5/9', 'D'] ); my @tmp = map {[$_, [split '/', $_->[1]]] } @table; my @sorted_tmp = sort { $a->[0][0] <=> $b->[0][0] # 第1フィールドで比較 or # 第1フィールドが同じなら $a->[1][0] <=> $b->[1][0] # 第2フィールドで比較 年 or $a->[1][1] <=> $b->[1][1] # 第2フィールドで比較 月 or $a->[1][2] <=> $b->[1][1] # 第2フィールドで比較 日 or # 第2フィールドも同じなら $a->[0][2] cmp $b->[0][2] # 第3フィールドで比較 } @tmp; my @sorted_table = map {$_->[0]} @sorted_tmp; # print Dumper(@sorted_table); デバッグ: 結果の確認 以上の手順で @sorted_tableにソートした結果が入ります。 map→sort→mapは一行にまとめてもよいのですが、そうすると さらにわかりにくくなると思うので分割しました。 興味があればシュオーツ変換(Schwartzian transform)で検索してみてください。

ma_trix
質問者

お礼

お礼おそくなりました。回答ありがとうございました。 いま自分で検証中なのですが、ひとつ上手くできません。 まず、↓のソートはできました @txt = sort { $a->[0] <=> $b->[0] or $a->[2] cmp $b->[2] } @txt; 第1フィールドと第3フィールドのソートは できました。 ↓の第2フィールドのソートができません。 $a->[1][0] <=> $b->[1][0] # 第2フィールドで比較 年 or $a->[1][1] <=> $b->[1][1] # 第2フィールドで比較 月 or $a->[1][2] <=> $b->[1][1] # 第2フィールドで比較 日 ためしに単純に (split(/\,/,$a))[1] cmp (split(/\,/,$b))[1] こんな感じのソートなら近いものができました。 ただ、 1999/2/12 1999/2/13 1999/2/15 1999/2/15 1999/2/8 1999/2/9 のようになってしまいます。つまり、一桁の数字が 後方に移動されます。 数値形式が 1999/02/08 の形式ならばちゃんとできるみたいです。 でも、1999/2/9形式でできればそれで実行させたい です。 それにはsakusaker7さんに教わった方法になるの でしょうが、第2フィールドのみ完全に上手く比較 されていないようなのです。 もしまたなにかヒントがあれば教えてください。

関連するQ&A

  • 複数ファイルから合計&ソートについて

    はじめまして、こんにちわ。 下記の処理がわからなくて困っています(^^; どなたか知恵を貸して頂ければ幸いですm(_ _)m 処理したいのは複数のファイルから合計を出し、数字の大きいものから順番に表示することなのです。 ファイルは各フォルダに同一のファイル名で存在します。 例: ./1/data.dat ./2/data.dat ./3/data.dat といった感じで 各data.datファイルの中身は 例(./1/data.dat): Aさん,56,… Bさん,28,… Cさん,75,… 例(./2/data.dat): Dさん,12,… Eさん,90,… Fさん,100,… といった感じです。 これを数字の大きい人からソートすると F・E・C・A・B・Dさん となるような感じの処理をご教授くださいm(_ _)m

    • ベストアンサー
    • PHP
  • こんなソートがしたいです。教えてください!

    エクセル2003で 下記のようなデータをソートし、 【ソート前】 2208550 92059184 92059174 92059174B 92059174A 92059174C 1348535 19777225 2519034 2519034D 2519034B 2519035A 2519035C 【ソート後】 1348535 19777225 2208550 2519034 2519034B 2519034D 2519035A 2519035C 92059184 92059174 92059174A 92059174B 92059174C 上記ソート後の結果を得られるマクロを作りたいです。 よろしくお願いいたします。

  • 2007/1/15形式をソートしたい

    予約カレンダーを作っています。 ユーザーは不特定の日を予約できます。 CSVファイル 2,1029,2007/1/15,C, 3,1029,2007/1/15,B,checked 4,1029,2007/1/10,D, 5,1029,2007/1/9,C,checked 6,1029,2007/1/16,D, 8,1023,2007/1/17,D 9,1023,2007/1/24,D 10,1023,2007/1/24,C 11,1023,2007/1/10,D ID,会員番号,日付,ステータス,承認 ソートがうまくいかず上記のように並んでいます。 理想としては 9,1023,2007/1/24,D 10,1023,2007/1/24,C 8,1023,2007/1/17,D 11,1023,2007/1/10,D のように日付が新しい方を上にして書き込みたいのです。 2007/1/24のところのソートが上手くいきません。 また、IDの順序も変わると新しいIDをつけるときに困りそうです。 なにかいい方法があったら教えてください。

    • ベストアンサー
    • Perl
  • 【Excel2010】複数の範囲をソートするには?

    初めまして、dtraと申します。 早速ですが質問を。 Excel2010を使用しているのですが、以下のような状態でExcelの機能・またはマクロを使ってソートをする方法はあるでしょうか? 1枚目 氏名 データ1 データ2 データ3... Bさん... Cさん... Dさん... 2枚目 氏名 データ1 データ2 データ3... Eさん... Fさん... と、データ数が多くなり印刷時の用紙が2枚以上になってしまう時に、 1枚目 氏名 データ1 データ2 データ3... Bさん... Cさん... Dさん... 2枚目 氏名 データ1 データ2 データ3... Eさん... Fさん... Aさん... このようにAさんのデータを入力した後、 1枚目 氏名 データ1 データ2 データ3... Aさん... Bさん... Cさん... 2枚目 氏名 データ1 データ2 データ3... Dさん... Fさん... Gさん... と、名前の昇順で全体をソートしたいのです。 今の所はデータを配列に格納してから新たに書き込ませる方法を取っていますが、データ量が多くなる事が予想されるので何か方法が無いかと質問に来ました。 解決策が思い浮かぶ方、どうか回答をお願いします。

  • 2つのフィールドを1フィールドの認識でソートする方法

    いつも拝見させて頂いております。 さっそくですが、SQLでのソート方法について悩んでおりまして解 決方法または参考資料等がありましたらご教授願えますでしょうか。 ある2つのテーブルからそれぞれの異なったフィールドを参照して2 つのフィールドを1つのフィールドとして認識してソートをかけたい のです。実際には各テーブルにあるKEYフィールドにてリンクをし て、ソートの対象は各テーブルにあるDATEフィールドです。 テーブルA  KEY  CHAR  DATE CHAR テーブルB  KEY  CHAR  DATE CHAR 実際のイメージとしては下記の様なイメージです。 テーブルA.KEY テーブルA.DATE テーブルB.DATE AAA       20040101    AAA       20040102    AAA       20040102    AAA                  20040102 AAA       20040103    条件としては 1.テーブルAとテーブルBが同一の日付であった時はテーブルBの   データを最後尾に持ってくる。 2.テーブルAとテーブルBのデータは別レコードになる様にする。 以上、このようなことができるかどうかわかりませんが、宜しくお願い致します。

  • 多段ソート

    C言語というよりはアルゴリズムの話です。 [名前], [生年月日] の2つのカラムで表される固定長の行データが羅列されたファイルがあります。 また、各カラムを比較して行をソートした場合にどの行が何番目にくるかといったインデックス情報を木構造で保持したファイルがあります。 (このファイルは行データの追加・削除時に更新される) これらのファイルを利用して、生年月日でソートし、かつ日時が同じ場合は名前順にソートした場合の上から10個分だけのデータを取り出したいのですが、効率のよい方法は無いでしょうか? 全データを読み込んでから、バブルソート等の順序を崩さないソートを多重にかけることはなるべく避けたいのです。 そのためにソート済みのインデックス的な役割を持つファイルを用意しているのですが、多段ソート時にどう応用すればよいのかわからなくなってしまいました。 例 日時、名前の順にソートされた上4つ分のデータが欲しい。 【一覧】 [1行目] 10/20, Aさん [2行目] 11/30, Fさん [3行目] 9/10, Cさん [4行目] 11/30, Bさん [5行目] 12/10, Dさん 【生年月日でソートされた インデックス】 9/10, 3行目 10/20, 1行目 11/30, 2行目 11/30, 4行目 12/10, 5行目 【名前でソートされた インデックス】 Aさん, 1行目 Bさん, 4行目 Cさん, 3行目 Dさん, 5行目 Fさん, 2行目 得たい結果 [3行目] 9/10, Cさん [1行目] 10/20, Aさん [4行目] 11/30, Bさん [2行目] 11/30, Fさん

  • 配列のソートについて質問です。

    配列のソートについて質問です。 2つのキーで配列の中身をソートしたいのですが、スマートな書き方があれば教えてください。 そもそも間違っている、などのご指摘でもありがたいです。 @t1 = map {(split /,/)[1]} @data; @t2 = map {(split /,/)[2]} @data; @data = @data[sort {$t1[$a] <=> $t1[$b] or $t2[$a] <=> $t2[$b]} 0 .. $#t1]; @dataの内容 A,1,2 B,1,3 C,2,1 D,3,2 E,3,1 F,1,1 出力結果 F,1,1 A,1,2 B,1,3 C,2,1 E,3,1 D,3,2 よろしくお願いします。

    • ベストアンサー
    • Perl
  • Access2010 テーブルのフィールドについて

    Access2010を使用しています。 テーブルのフィールド定義 [A][B][C][D][E][F][G] ↓ テーブルを開くと [A][B][C][E][F][G][D] と勝手に変わる (あるフィールドだけ、別の場所に移動) ↓ フィールドの並び順を [A][B][C][D][E][F][G] に戻す ↓ 保存してテーブルを閉じる ↓ 再度開くと [A][B][C][E][F][G][D] と変わってしまう。 この繰り返しです。 どなたか、お助け下さい。 よろしくお願いいたします。

  • 複数のフィールドからSELECT

    MySQLのテーブルに4つフィールドがあります。  A | B | C | D ------------------------ 日付|用件|日付|用件 日付|用件|日付|用件 日付|用件|日付|用件 上記のような感じでデータが入っているとします。 (AとBが関連する内容、CとDが関連する内容) これをAとCのフィールド合わせた値全てから最近の日付順に並べ替え、 例えば、 日付-用件(A-B) 日付-用件(B-D) 日付-用件(A-B) 日付-用件(A-B) 日付-用件(B-D) のようにするにはどういう具合にPHPを表記すればいいのでしょうか?ネットで調べましたが、分かりませんでした。 どなたか分かる方、お手数ですが手ほどきをお願い致します<(_)>。

  • ACCESS、フィールドが異なるデータのインポート

    例えば ファイル1 フィールド A B C D E データ   1 2 3 4 5 ファイル2 フィールド A C D E データ   6 7 8 9 のように、フィールドの項目数が異なるデータをインポートする場合は どのようにすればいいのでしょうか? アンケートのメールを処理するのですが、応えられていない項目についてはデータが無いもので・・・ ちなみにインポート処理さえ出来るのであれば、エクセルでもかまいません。 すみませんがよろしくお願いします。

専門家に質問してみよう