[PHP-users 18070]Re: 二つのキーを使用してソートしたい。

KOYAMA Tetsuji koyama @ hoge.org
2003年 9月 25日 (木) 18:27:46 JST


  小山です。

At Thu, 25 Sep 2003 15:57:34 +0900,
Yutaka Miura wrote:
> 一つのキーを使用してソートはできたのですが、
> 二つのキーでソートしようと場合
> どのように組んだらよいでしょうか?
> ご教授願いますでしょうか?

> $data[0][0] = 3;
> $data[1][0] = 1;
> $data[2][0] = 2;
> $data[3][0] = 3;
> $data[4][0] = 2;
> $data[5][0] = 1;
> $data[6][0] = 3;
> 
> $data[0][1] = 20030925;
> $data[1][1] = 20030925;
> $data[2][1] = 20030925;
> $data[3][1] = 20030924;
> $data[4][1] = 20030925;
> $data[5][1] = 20030925;
> $data[6][1] = 20030924;
>
> function cmp($a, $b) {
>     return strcmp($a[1],$b[1]);
> } 
> 
> usort($data, "cmp"); 

  usort() を使うところまでは良いのですが、なぜその比較関数 cmp() の中
で文字列比較をしているのでしょうか? もしかして 20030925 などの数値は文
字列のつもりなのでしょうか? そうであるなら

$data[0][1] = '20030925';

のようにきちんと文字列であることを明示した方が、ソースも見やすくなりま
すし、思わぬトラブルにも合わなくてすみます。

  さてどのようにして2次元の配列をソートするかですが、その前にまず、比
較関数(この場合は cmp()) の引数には何が入るか考えてみましょう。

  $data は 2次元配列なので、例えばその一つの要素 $data[0] もまた配列に
なり、array(3, 20030925) という値が入っています。ということは cmp() に
渡される引数も $data[0] と同様の値、つまり配列になります。

> 求めたい結果
> 1 : 20030925
> 1 : 20030925
> 2 : 20030925
> 2 : 20030925
> 3 : 20030925
> 3 : 20030924
> 3 : 20030924

  この希望結果から、ソート条件を考えると

  1. まず $data[?][] を降順でソートし、
  2. 次に $data[][?] を昇順でソートする

ということになります。以上を踏まえて比較関数を書くと

function cmp($a, $b) {
    // まず最初の項で比較
    $result = $a[0] - $b[0];
    // もし同じ値なら
    if ($result == 0) {
        // 2番目の項で比較。(昇順なので符号を逆にする)
        $result = -($a[1] - $b[1]);
    }
    return $result;
} 

のようになります。(2項目めは数値として扱っています)

  別に難しいことではないので、上記のように順序だてて考えてみましょう。

-- 
	小山 哲志@ビート・クラフト
	koyama @ beatcraft.com
	koyama @ hoge.org


PHP-users メーリングリストの案内