
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関数系の使い方がわかりません。
識者の方よろしくご教授いただけますようお願いします。
No.2ベストアンサー
- 回答日時:
クイックソートは、配列中の値の位置をどんどん「交換」していくことで処理してきます。
ですから、実際の内部処理中では、「交換する or 何もしない」の2つしかありません。これを、比較関数によって決めます。ユーザ比較関数が0を返す場合、それらは同値とみなして、「それらのメンバーの並び順は未定義」ということです。
「最初の引数のほうが二番目の引数より大きい場合は正の数」とマニュアルにありますが(1ではなくて2でも3でもよい)、これは、単にそういう風にusort関数側が要請しているわけです。こちらはその通りに比較関数を決めるだけでよい、ということです。
実際のphpのusort関数のソースコードを見ましたが、やはり、クイックソートを使用し、また、非再帰で実装しています。(この場合、スタックを使用し、より分かり辛いコードになります)
なぜマニュアルでこのあたりの仕組みを記述しないか、といえば、
・知る必要がほとんど無い
・ソートアルゴリズムの学習をする場所ではない
・知りたい人はソースコードを読んで
というようなことだと思います。また、c言語やjavaなどでソートを扱った人にとっては、phpのソート関数の使用法は自明のように思われます。
ぜひともクイックソートなどのソートアルゴリズムを学んでください。
No.1
- 回答日時:
usort関数は、多分クイックソートというアルゴリズムを改良したものを使っていると思うのですけど、それらソートアルゴリズムを少しでも齧っている人にとっては、特に引っかかることはありません。
(Wikipediaを見てください)クイックソートでは、配列中のデータを何度も何度も比較しながら、順序の入れ替えを何度も何度も行っていき、最終的にデータの整列した状態に持っていきます。
この際、比較する基準というのは、基本的にはユーザー側しか知らないため、この関数をユーザーに作らせて、それを指定させます。
「$a,$bはいったいどんな順番」というのは、これは不定期に何度も呼ばれることになります。
0,-1,1を返した時、何が行われているか、というと、ユーザーがそうやって知らせてくれた情報を元に、このusort関数は、データの順番を入れ替える作業をしています。
usort関数のマニュアルに、「4.1.0 新しいソートアルゴリズムが導入されました。」ということが書いてるんですが、特にどういうアルゴリズムか、ということは記述されていません。どういうアルゴリズムかは使用者が知る必要は無く、ただ、比較する際の基準をusort関数に教えてやれば、あとは勝手にやってくれます。
(ただ、4.1.0から微妙に結果が変わっているという点は、何人かが頭を傾げたことになったかもしれません・・・)
ありがとうございます。
$a,$bは第一引数に与えられた配列の総あたりというかすべての条件で比較していくかんじなのですね・・・。
また確認ですが$a $bを比較した際に返す値の0,-1,1
なんですが、これて0を返したときはその時(何回目の比較かわからないけど、)
ユーザー関数にあたえられた$aと$bは同じ値だから順不同でかまわないということをいみしているのですよね?逆に-1を返すときは、その比較回数目の時の$aを$bより配列の順位てきに若い方へ持っていくという意でしょうか?逆に1を返したときは、$aを$bより配列の順位が後になる用に入れかえる・・・わかりやすくかくと
//==================================================================================================//
/* $aを配列順の若い方へ・・・・・・・・中間(順不同)・・・・・・・・・$aを配列順の後方へ */
/* 返り値【-1】・・・・・・・・・・・・返り値【0】・・・・・・・・・・・・・・・返り値【1】 */
//===================================================================================================//
と上記のような配置にするというかんじですかね?
このへんが非常にわかりにくいです。
PHPのマニュアルもこの返り血について詳しく触れていないので・・・・。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- Excel(エクセル) エクセル 関数について質問です。 2 2022/10/03 11:14
- JavaScript 正規表現について質問です。条件に合う場合はtrueを返したい 3 2022/10/06 23:02
- JavaScript ソースコードのいじる場所が分かりません。 1 2022/12/23 02:06
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- PHP PHP MySql ページング 2 2022/09/20 06:38
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【PHP】配列内のある値以上をカ...
-
file_existsでファイル名の部分...
-
PHPの問題を解いているのですが…
-
配列のからの要素に代入
-
重複しないランダム関数を教え...
-
ネストが深い時のforeachはどう...
-
$_SESSIONに二次元配列を使える...
-
AならBを読み込む場合
-
空フィールドが表示されない
-
ランダム表示について
-
C言語の配列をPush(追加)する...
-
preg_replaceでの警告
-
MYSQLとPHPによって取得する多...
-
正規表現
-
ファイルの読み書きでエラー
-
Tableの背景色を交互に変えたい
-
usortで3つの項目を昇順・降順...
-
foreachの実行結果について
-
二次元配列の削除
-
配列の比較
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
String だと「 ByRef引数の型が...
-
配列をループでたくさん宣言し...
-
$_SESSIONに二次元配列を使える...
-
チェックボックス複数選択 mys...
-
配列一致(要素順番は違うが内容...
-
file_existsでファイル名の部分...
-
Smartyのテンプレートからjavas...
-
ネストが深い時のforeachはどう...
-
foreachのなかで次のキーを参照...
-
漢字のソートについて
-
PHPにてクラスを配列にすること...
-
ExcelVBAのチェックボックスに...
-
URLのサブドメインとドメイン部...
-
PHPのカッコ[ ]の使い方について
-
配列を回すとき、最後の要素だ...
-
PHPのPOSTでの半角スペース
-
PHPのループ数限界値について
-
$_POSTを一括してサニタイズし...
-
postgresql関数をつかったレコ...
-
ファイルから指定行数分だけ読...
おすすめ情報