2011-06-25 11 views
6

最初の例:比較配列 - 面白い行動

$x = array("a" => 1, "b" => 2); 
$y = array("b" => 1, "a" => 2); 
$xLessY = ($x < $y); 
$xGreaterY = ($x > $y); 
var_dump($xLessY, $xGreaterY); 

結果:$ xLessY = 、$ xGreaterY =

第二の例:

$x = array("a" => 2, "b" => 1); 
$y = array("b" => 2, "a" => 1); 
$xLessY = ($x < $y); 
$xGreaterY = ($x > $y); 
var_dump($xLessY, $xGreaterY); 

結果:$ xLessY = 、$ xGreaterY =

http://docs.php.net/manual/en/language.operators.comparison.php上のドキュメントによると:オペランド1から鍵が オペランド2に見つからない場合

その後、配列はuncomparable あり、そうでない場合は - 配列$ xから各キーが配列$ yに存在する我々の場合の値

によって値を比較するので、$ xと$ yはCOMPであります耕作可能。 も参照してくださいドキュメントからの例:

// Arrays are compared like this with standard comparison operators 
function standard_array_compare($op1, $op2) 
{ 
    if (count($op1) < count($op2)) { 
     return -1; // $op1 < $op2 
    } elseif (count($op1) > count($op2)) { 
     return 1; // $op1 > $op2 
    } 
    foreach ($op1 as $key => $val) { 
     if (!array_key_exists($key, $op2)) { 
      return null; // uncomparable 
     } elseif ($val < $op2[$key]) { 
      return -1; 
     } elseif ($val > $op2[$key]) { 
      return 1; 
     } 
    } 
    return 0; // $op1 == $op2 
} 

この動作は本当に奇妙です:$ xは$ yよりも小さくなると同時に、$ xは$ yを(第1例)よりも大きく、二つの配列が同等です。

これは、phpが常に '<'という特定の側から比較しているからです。つまり、for($ x < $ y)phpはオペランド1として$ xをとりますが、($ x> $ y)はオペランド1として$ yをとりますが、ドキュメントでこの動作について何も見つかりませんでした。
これについてあなたの考えは?

+0

第1オペランドとして '<'の最後の値がどのように使用されるのか、あなたは正しいかもしれないと思います。もちろん、あなたはPHPソースコードを見れば答えを見つけることができます... –

答えて

0

私は間違っているかもしれませんが、私はあなたがそのように配列を比較できるとは思わない。私はいつも平等か不平等かをチェックできると思っていますが、<と>と量を比較することはできません。

man page on array operatorsはこれを確認しているようです。

+0

[別のmanページ](http://php.net/manual/en/language.operators.comparison.php)があります。 。 「複数の型との比較」の表と以下のテキストを参照してください。「より少ないメンバの配列は、オペランド2のキーがオペランド2に見つからない場合、配列が比較不能である場合は小さく、そうでない場合は値と値を比較します(次の例を参照) 。また、私が書いたサンプル(standard_array_compare関数)もあります – Andy

1

あなたの前提は正しいです。 >オペレータはX > Yは比較が可換でないときはもちろん間違っているnot X < Y、と等価である、

| expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); } 

これは基本的に言うように解析されます。 bugs.php.netでこれを報告することを検討してください。

+0

Commutative? 'X> Y'は可換であるということは' X> Y'が 'Y> X'と等価であることを意味します。加えて、 "比較(btw)が可換でない"ということは、 'X> Y'が' not X Y'は' not X $ y'と' $ y> $ x'が真であるため検証されない反対称性が期待されます。 $ x!= $ y'。 – Artefacto

+0

連想配列を賢明に覚える方法はないと私は同意しますが、これは任意の順序を設定することは有用ではないことを意味するわけではありません。例えば、多くのアルゴリズムは順序付けされるデータに依存します。しかし、現在の状況では、配列の世界全体で順序は存在しないだけでなく、マニュアル定義の配列が実際には '<' and '>'の間に一貫性を持たない配列も存在します。 – Artefacto

1

$y < $xの代わりに$x > $yのバグがあります。

確かに、$x > $yを、比較関数に渡されたときに引数が位置を交換しないように実装した場合は、この特定の問題を解決できます。しかし、あなたは別のものを受け取ります。

は、今あなたがしている:最初の引数の最初のキーは常に最初に比較され

$x < $y <=> cmp($x, $y) == -1 
$x > $y <=> cmp($y, $x) == -1 

のでreset($x) < $y[key($x)]reset($y) < $x[key($y)]場合、両方の条件が真です。

しかし、この問題を解決するだろう別の実装、考える:オペランドの順序が固定されているときに

$x < $y <=> cmp($x, $y) == -1 
$x > $y <=> cmp($x, $y) == +1 

<>は一貫しているが、我々は我々ので、オペランドを交換するとき、私たちは今、奇妙な振る舞いを取得しますcmp($x, $y) == -1およびcmp($y, $x) == -1を有することができ、これは、$x < $yおよび$y < $xの両方が真であることを意味する。総じて、唯一の解決策は、その挙動が反対称になるように、すなわち少なくともcmp($x, $y) == - cmp($y, $x)が比較可能であると主張されている要素のセット内で比較関数を修正することである。

+0

私は、この動作 '$ x <$ y == -1'と' $ y <$ x == -1'は、順序のない配列の場合にはもっと理解できると思います。そして、これはドキュメントとより一貫しています。 – Andy

+0

これはバグではないかもしれませんが、 – Andy