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

PHPにおけるusort関数およびuasort uksort関数の使い方がわかりません。

$array = array("b" => "bbbb","c" => "cc","d" => "ddddddddddd","e" => "eee","a" => "a","f" => "ffffffff","g" => "gg","h" => "hh");
上記のような配列があった場合

uasort($array,
function($a,$b){
if (strlen($a) == strlen($b)) {
return 0;
}

if(strlen($a) > strlen($b)){
return -1;
}else if(strlen($a) < strlen($b)){
return 1;
}
}
);
print_r($array);

上記のようなコードの場合
(
[d] => ddddddddddd
[f] => ffffffff
[b] => bbbb
[e] => eee
[h] => hh
[g] => gg
[c] => cc
[a] => a
)

という結果がかえてきます。
ただ、実際このコードでなにがおきてるかわかりません。
まず、uasort関数の第二引数に渡す関数の引数 $a,$bはいったいどんな順番で第一引数の配列からわたされているのでしょうか?

そして、$a と$ bの値が同じ場合に0を返した場合なにがおきてるのでしょうか?
同じく return 1;を返すときと
return -1;を返すときと
いったいどのような処理がおこなわれていてどういうなぜ 上記のような配列を返すことになるのでしょうか?
そもそも
PHPマニュアルから参照しますが
比較関数は、最初の引数と二番目の引数の比較結果を返します。最初の引数のほうが二番目の引数より大きい場合は正の数を、二番目の引数と等しい場合はゼロを、そして二番目の引数より小さい場合は負の数を返す必要があります。
上記説明も、どうにも理解できません。

どうも全体的にusort関数系の使い方がわかりません。
識者の方よろしくご教授いただけますようお願いします。

A 回答 (2件)

クイックソートは、配列中の値の位置をどんどん「交換」していくことで処理してきます。

ですから、実際の内部処理中では、「交換する or 何もしない」の2つしかありません。これを、比較関数によって決めます。

ユーザ比較関数が0を返す場合、それらは同値とみなして、「それらのメンバーの並び順は未定義」ということです。
「最初の引数のほうが二番目の引数より大きい場合は正の数」とマニュアルにありますが(1ではなくて2でも3でもよい)、これは、単にそういう風にusort関数側が要請しているわけです。こちらはその通りに比較関数を決めるだけでよい、ということです。

実際のphpのusort関数のソースコードを見ましたが、やはり、クイックソートを使用し、また、非再帰で実装しています。(この場合、スタックを使用し、より分かり辛いコードになります)
なぜマニュアルでこのあたりの仕組みを記述しないか、といえば、
・知る必要がほとんど無い
・ソートアルゴリズムの学習をする場所ではない
・知りたい人はソースコードを読んで
というようなことだと思います。また、c言語やjavaなどでソートを扱った人にとっては、phpのソート関数の使用法は自明のように思われます。
ぜひともクイックソートなどのソートアルゴリズムを学んでください。
    • good
    • 0

usort関数は、多分クイックソートというアルゴリズムを改良したものを使っていると思うのですけど、それらソートアルゴリズムを少しでも齧っている人にとっては、特に引っかかることはありません。

(Wikipediaを見てください)

クイックソートでは、配列中のデータを何度も何度も比較しながら、順序の入れ替えを何度も何度も行っていき、最終的にデータの整列した状態に持っていきます。
この際、比較する基準というのは、基本的にはユーザー側しか知らないため、この関数をユーザーに作らせて、それを指定させます。

「$a,$bはいったいどんな順番」というのは、これは不定期に何度も呼ばれることになります。
0,-1,1を返した時、何が行われているか、というと、ユーザーがそうやって知らせてくれた情報を元に、このusort関数は、データの順番を入れ替える作業をしています。

usort関数のマニュアルに、「4.1.0 新しいソートアルゴリズムが導入されました。」ということが書いてるんですが、特にどういうアルゴリズムか、ということは記述されていません。どういうアルゴリズムかは使用者が知る必要は無く、ただ、比較する際の基準をusort関数に教えてやれば、あとは勝手にやってくれます。
(ただ、4.1.0から微妙に結果が変わっているという点は、何人かが頭を傾げたことになったかもしれません・・・)
    • good
    • 0
この回答へのお礼

ありがとうございます。
$a,$bは第一引数に与えられた配列の総あたりというかすべての条件で比較していくかんじなのですね・・・。

また確認ですが$a $bを比較した際に返す値の0,-1,1
なんですが、これて0を返したときはその時(何回目の比較かわからないけど、)
ユーザー関数にあたえられた$aと$bは同じ値だから順不同でかまわないということをいみしているのですよね?逆に-1を返すときは、その比較回数目の時の$aを$bより配列の順位てきに若い方へ持っていくという意でしょうか?逆に1を返したときは、$aを$bより配列の順位が後になる用に入れかえる・・・わかりやすくかくと
//==================================================================================================//
/* $aを配列順の若い方へ・・・・・・・・中間(順不同)・・・・・・・・・$aを配列順の後方へ */
/* 返り値【-1】・・・・・・・・・・・・返り値【0】・・・・・・・・・・・・・・・返り値【1】 */
//===================================================================================================//

と上記のような配置にするというかんじですかね?
このへんが非常にわかりにくいです。
PHPのマニュアルもこの返り血について詳しく触れていないので・・・・。

お礼日時:2012/06/19 21:49

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