PHPの多次元配列のソートについて相談させてください。


コメント欄のようなデータ群があるのですが、
$row[n][1]キーを軸に重複しているものをまとめて表示したいと考えています。
※データ群の中では「2」が3つ、「7」「4」が1つずつです。

このような場合どのような処理の仕方をすればよいでしょうか。

ご知見あるかたご教授お願いたします。






回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2012/02/25 22:18:26
  • 終了:2012/03/03 22:20:05

回答(1件)

id:windofjuly No.1

うぃんど回答回数2625ベストアンサー獲得回数11492012/02/25 22:56:38

ポイント200pt

array_multisort という関数があります

<?php
$row = Array(
    Array(  4, 2, 'eeeee'),
    Array(  3, 2, 'bbbb'),
    Array(  8, 7, 'hoge'),
    Array(  3, 2, 'test'),
    Array( 12, 4, 'aaa')
);
array_multisort( $row ) or die('ソート失敗');
print_r( $row );

http://www.php.net/manual/ja/function.array-multisort.php

話は変わりますが、
$rowって変数名から想像するにデータベースから取り出したものですよね?
データベースから配列に全部読み取って、
php側でソートしたり集計したりするよりも、
データベース側で集計やソートを行って、
php側では1行読み取っては出力するという方式のほうが処理も早いし管理も楽ですよ

追記:
特定の列でソートしたい場合なので、自分で比較関数を用意することになりますね

<?php
$row = Array(
    Array(  4, 2, 'eeeee'),
    Array(  3, 2, 'bbbb'),
    Array(  8, 7, 'hoge'),
    Array(  3, 2, 'test'),
    Array( 12, 4, 'aaa')
);

function cmp($a , $b){
    return ($a[1] >= $b[1]);
}

usort( $row, "cmp" ) or die('ソート失敗');
print_r( $row );

http://www.php.net/manual/ja/function.usort.php

総当りでユーザー関数(上記では cmp 関数)がそれぞれ実施され、
ユーザー関数の返り値の真偽によって入れ替えが行われるため、
思い通りの順番にならないこともあります

他の列も含めて思い通りの順番で出力したい場合は、
下記のように関係する列すべての評価を行わせることが必要となってきます

return ($a[1] >= $b[1]) * ($a[0] >= $b[0]);

たった一箇所のためだけに関数を作りたくない場合は無名関数を使う

<?php
$row = Array(
    Array(  4,2,'eeeee'),
    Array(  3,2,'bbbb'),
    Array(  8,7,'hoge'),
    Array(  3,2,'test'),
    Array( 12,4,'aaa')
);
usort( $row,function($a, $b){ return ($a[1] >= $b[1]) * ($a[0] >= $b[0]); } ) or die('ソート失敗');
print_r( $row );

http:/php.net/manual/ja/functions.anonymous.php

id:kuso47

ありがとうございます。やはりmysql側で処理したものを返してもらったほうがよいのでしょうか。mysql側の負荷とphpのメモリーリーク?どちらがサーバ側にやさしいのかわかっていませんでした。DB側のほうでなにか参考になるサイトなどありませんでしょうか。。

2012/02/25 23:33:15
id:windofjuly

メモリリークではなく「利用するメモリの増大」という話なので、
自宅で個人利用するだけならばphp.iniなどで利用するメモリの量を増やしていけば良いだけとなります

それよりも何よりもphpに自分で書いたスクリプトを動かすより、
データ処理が専門のMySQLに集計やソートをさせるほうが断然早く、
1台でphp+MySQLの場合だけでなく、アプリサーバー(php)と、
データベースサーバー(MySQL)の2台に分けている場合でも、
適度に分業できるということになり、これまた有効な手段となります

そのため、
php+MySQL用に書かれた多くのスクリプトは1行1行読み取りながら処理するようなものばかりです
matさんが行っているように多次元配列にすべて読み取ってからというほうは少数派(希少派?)です

MySQLで一番参考になるのは公式サイトのドキュメントですが、
ソートの指定はSQLの ORDER BY で必要なフィールドを指定するだけなので、
ドキュメントを見るまでもないかもしれません
http://dev.mysql.com/doc/refman/5.1/ja/select.html
http://dev.mysql.com/doc/refman/5.1/ja/order-by-optimization.html

2012/02/25 23:57:08
  • id:kuso47
    $row = Array (
    [0] => Array (
    [0] => 4
    [1] => 2
    [2] => eeeee
    )
    [1] => Array (
    [0] => 3
    [1] => 2
    [2] => bbbb
    )
    [2] => Array (
    [0] => 8
    [1] => 7
    [2] => hoge
    )
    [3] => Array (
    [0] => 3
    [1] => 2
    [2] => test
    )
    [4] => Array (
    [0] => 12
    [1] => 4
    [2] => aaa
    )
    )

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません