- ベストアンサー
phpでのソートについて
- phpのソート処理で日付の新しい順に並び替える方法を知りたいです。同じ日付の場合にも正しい順番で並び替えたいです。
- ソート処理で同じ日付の場合にランダムな順番ではなく、元のリストの上から順番に並び替えたいです。
- 具体的なソースコードを教えていただけると助かります。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
もしCSV形式としてそのファイルが有効であれば、fgetcsv関数とfputcsv関数が向いていると思います。 PHP Manual - fgetcsv http://php.net/manual/ja/function.fgetcsv.php PHP Manual - fputcsv http://php.net/manual/ja/function.fputcsv.php Pentan.info - fgetcsv関数を文字化け対応 setlocaleの文字コード指定 http://pentan.info/php/fgetcsv_char.html ただ、一度全部の行を1行ずつ配列に読み込ませてはまた1行ずつ保存していくってすごく無駄ですよね。2万件あるなら結構きついと思います。そういうときはシリアル関数の出番です。PHPでは配列をそのままの形で保存したり復元したり出来ます。これであれば10万件程度までは何とかなるでしょう。 PHP Manual - unserialize http://php.net/manual/ja/function.unserialize.php PHP Manual - serialize http://php.net/manual/ja/function.serialize.php それ以上の世界となると、MySQLなどのデータベースを利用する選択肢に限られてきます。以下の回答を参考にどうぞ。 http://okwave.jp/qa/q8501002.html こちらの方法ならば、kmeeさんのおっしゃる通り行番号をあらかじめ用意しておき、 SELECT * FROM table_name ORDER BY date_value DESC, index_value ASC みたいな感じのSQLになると思います。
その他の回答 (3)
一応補足しておきますね… ソートの説明についてはkmeeさんの回答が非常に参考になると思います。私の回答では「行番号」に配列のキーをそのまま使用するようにして実現しました。usort関数は値でソート、uksort関数はキーでソートするために使われますが、uksort関数とコールバック関数でのuse句を組み合わせれば、キーと値の両方の情報を同時に使うことが出来ます。 uksort関数の場合、そのままではキーの添え字が維持されるので、振りなおしたい場合はarray_values関数を最後に通す必要があります。
<?php $data = array( array('aaa-12', 'dmy', '2014年3月5日'), array('ccc-22', 'dmy', '2014年3月5日'), array('ddd-43', 'dmy', '2014年3月4日'), array('yyy-45', 'dmy', '2014年3月5日'), array('ddd-43', 'dmy', '2014年3月2日'), ); uksort( $data, function ($a, $b) use ($data) { return $data[$a][2] == $data[$b][2] ? ($a < $b ? -1 : 1) : ($data[$a][2] < $data[$b][2] ? 1 : -1) ; } ); $data = array_values($data); // 添え字を振りなおす場合は必要 foreach ($data as $key => $value) { $value = implode(', ', $value); echo "[{$key}] {$value}\n"; } ideone.comでの動作確認 http://ideone.com/cBLHu3
補足
お忙しい中ご回答いただきましてありがとうございます。 完全なご回答をいただきながら以下部分でつまづいてしまっております。 $data = array( array('aaa-12', 'dmy', '2014年3月5日'), array('ccc-22', 'dmy', '2014年3月5日'), array('ddd-43', 'dmy', '2014年3月4日'), array('yyy-45', 'dmy', '2014年3月5日'), array('ddd-43', 'dmy', '2014年3月2日'), ); こちらをaaa.txtに置き換えして実行したいのですが、 $datax = @file('aaa.txt'); $data = array($datax); これでは駄目なのでしょうか。 色々やってはみたいのですが上手くいかず、 知識がなさすぎて申し訳ありません。 自分なりに調べてからどうしてもわからない場合にお願いをさせていただくのですが、 arrayでの例題が多く、txtファイルなどを使った場合、 どのようにこれを置き換えすれば良いのかが全然理解できておりません。 また、aaa.txtは2万行ぐらいありまして、今後も増えていくのですが あまり増えますとご教授いただいた形ですと厳しいでしょうか。 知識がなさすぎてご迷惑をおかけして申し訳ありません。 もし宜しければご指導いただけますと幸いです。
- kmee
- ベストアンサー率55% (1857/3366)
ソートには、 同じ「順位」だったときに、元の順番が保存される「安定ソート」 と どうなるかわからない「不安定ソート」 があります。 http://php.net/manual/ja/function.usort.php > 比較結果が等しくなるメンバーが複数存在する場合、 ソート後の配列でのそれらのメンバーの並び順は未定義となります。 と、usortのマニュアルに明記してあります。 つまり、不安定ソートです。(少なくとも、安定ソートとは決めつけることはできない) # http://www.php.net/manual/ja/array.sorting.php # によると、usortだけではなく、他のソートも不安定ソートです。 対策は (1) 用意されたsortではなく、自前で安定ソートのプログラムを用意する (2) 不安定にならないように工夫する のどちらかです。 (1)は他言語のものは見つかりますが、PHPで書かれたものは少ないように思います。 (2)は、不安定になるのは同順位のときなのですから、絶対同一順位にならないようにします 例えば 1,aaa-12,dmy,2014年3月5日, 2,ccc-22,dmy,2014年3月5日, 3,yyy-45,dmy,2014年3月5日, 4,ddd-43dmy,,2014年3月4日, 5.ddd-43,dmy,2014年3月2日, 等と「行番号」を付けて、cmpを「日付が同じなら行番で比較」というように変更します。
お礼
考え方をご教授いただきましてありがとうございます。 自前で作成できるだけのスキルが全然ありませんので 既存のもので少しずつ理解をしていくしかないようです。 番号を最初につけておいて・・と言う所も大変参考になりました。 お忙しい中、ご面倒にも関わらずありがとうございました。
お礼
お忙しい中、ご回答ありがとうございます。 こちらをヒントにして、一度、安定ソートしたデータを 別に保存しておいて、新たに追加されたデータのみを対象にして 安定ソートをかけた後に保存しておいたデータと合算させることにより 無理なく処理が可能になりました。 ありがとうございました。