アプリ版:「スタンプのみでお礼する」機能のリリースについて

PHPマニュアルにあるusortの説明がうまく理解できなくて悩んでいます。
そこでは、パラメータとなる比較関数について次のように書かれています。

「比較関数は、最初の引数と二番目の引数の比較結果を返します。最初の引数のほうが二番目の引数より大きい場合は正の数を、二番目の引数と等しい場合はゼロを、そして二番目の引数より小さい場合は負の数を返す必要があります。」
http://php.net/manual/ja/function.usort.php

「usort() の例」として提示されているのは以下です。

function cmp($a, $b)
{
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");


この例のユーザー定義の比較関数cmpは、前述の説明の通りに書かれているので理解できます。
しかし、ユーザーページの投稿にもありますが、($a > $b) としたり、($a < $b) ? 1 : -1 のように返り
値を変えて降順(逆順)にソートするという使い方を普通に見かけます。

これは、「最初の引数のほうが二番目の引数より大きい場合は正の数を(……)二番目の引数より小さい場合は負の数を返す必要があ」るという説明とは矛盾しています。
「必要」とまで書いているのでかなり強い指示だと思います。英語版でも「must」となっているので翻訳上の問題はなさそうです。

また、「配列のソート」ページによるとソート順は「ユーザー定義」とあり、件の比較関数次第ということになっています。
http://www.php.net/manual/ja/array.sorting.php

ということは、逆順であれ自然順であれ可能だとこれは示唆しているのだと思うのですが、やはり説明部分との矛盾が気になります。

……どう捉えたらよいのでしょうか?

A 回答 (5件)

何をもって大きいとするかを指定できる仕様なのです



例えば、トランプの場合、1が13よりも大きい数字になったりしますよね

文字列の"2" と文字列の"10" では、先頭の文字が "1" と "2" なので "2" の方が
大きくなります。 でも実際は、"10" なのでこちらを大きくしたいと考える場合が
ありますよね、何をもって大きいとするかを決めるのは、設計者の仕様のはんちゅうです。
    • good
    • 0
この回答へのお礼

評価としての大小、ということですね。理解できました。ありがとうございます。

お礼日時:2013/08/29 23:42

慣例として「大きい」「小さい」っていっちゃうんだけど, 「後ろに来る」「前に来る」と書いてあるものだと思ってください.

    • good
    • 0
この回答へのお礼

たしかに、ソートして上にしたいものを、みたいにそのまま捉えると理解できます。ありがとうございました。

お礼日時:2013/08/29 23:44

「最初の引数のほうが二番目の引数より大きい場合は正の数を(……)二番目の引数より小さい場合は負の数を返す必要がある」



「配列の中から任意に2要素$a,$b(但し$aの方がかならず左にある)を取り出したとき、$aと$bを入れ替える必要があれば正の数を、入れ替える必要が無ければ負の数を返す必要がある」

と置き換えて考えてください。
(実際には等しい場合は0を返したほうがソートの効率がよくなると思われます)

こちらのC言語のバブルソートのプログラムをご覧ください。
http://www1.cts.ne.jp/~clab/hsample/Sort/Sort1.h …

if (x[j - 1] > x[j]) { /* 前の要素の方が大きかったら */

この行を

if (cmp_function(a, b)) { /* 前の要素の方が大きかったら */

に置き換えるのがusort関数と考えると分かりやすいですかね?
(実際にPHPが行っているのはバブルソートではなく、クイックソート・マージソートなどの併用ソートですが)
    • good
    • 0
この回答へのお礼

分かりやすい例をありがとうございます。文字通りに捉えすぎたようです。理解できました。

お礼日時:2013/08/29 23:45

一番目の引数の値は、2、 二番目の引数の値は、5 だったとして、


2と5、あなた決めたルールでは、どちらを大きいとしますか?

数字なら5の方が大きいでしょう、では、数字ではなくコードだとしたら?

あなたの作成するプログラムでは、
コードの2は、ドラゴン、 
コードの5は、スライムかもしれません。

モンスターの名前順、レベル順、攻撃力順、
あるいは、モンスターの名前の逆順、レベルの逆順、攻撃力の逆順

モンスターの名前順なら、「あ」が一番小さく、「ん」が一番大きいとして
名前の逆順なら、「ん」が一番小さく、「あ」が一番大きい値です。

レベル順なら、レベル1が一番小さく、レベル99が一番大きい値です
レベル逆順は、レベル99が一番小さな値で、レベル1が一番大きな値です

そもそも、
数字の2と5を比較して5の方が大きいから負の数を返すなら、この関数の存在意義が無いですよね
    • good
    • 0
この回答へのお礼

たしかに、例示されているのが数値ではなく文字列だったら疑問に思わなかったかもしれません。ありがとうございました。

お礼日時:2013/08/29 23:46

データの大小と、順列番号の大小は別 なのですが、質問者さんの引っかかってる「must」については、日本語の語順に惑わされてるようです。


must return an integer は、返値は、Integer型で返す必要があるの意味。
引数比較については considered to be respectively なので、どっちを大きい(順列の後方)と考えるかによって返値を調整しろということ。「必ず大きい方」ではない。
日本語にすると語順的にどこに「必要」がかかってるか解りにくいのが欠点ではある。ていうか「整数」が抜けてるせいか?
    • good
    • 0
この回答へのお礼

ありがとうございます。理解できました。

お礼日時:2013/08/29 23:49

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!