in_array
関数はオブジェクトを比較できますか?
たとえば、オブジェクトの配列があり、それらを別の配列に個別に追加したいとします。次のように、オブジェクトが既に追加されているかどうかを確認することは可能ですか?
in_array($distinct, $object);
または他の方法はありますか?
in_array
関数はオブジェクトを比較できますか?
たとえば、オブジェクトの配列があり、それらを別の配列に個別に追加したいとします。次のように、オブジェクトが既に追加されているかどうかを確認することは可能ですか?
in_array($distinct, $object);
または他の方法はありますか?
厳密な比較を使用できます。
in_array($object, $array, TRUE);
使用例:
$a = new stdClass();
$a->x = 42;
$b = new stdClass();
$b->y = 42;
$c = new stdClass();
$c->x = 42;
$array = array($a,$b);
echo in_array($a, $array, true); // 1
echo in_array($b, $array, true); // 1
echo in_array($c, $array, true); //
in_array
オブジェクトと関数を比較するいくつかのテストを行いました。これが私の結論です:
配列内のオブジェクトの同じインスタンス(OP など)を検索しようとするin_array
と、厳密な比較ブール値セットを使用できます。
同じクラスでインスタンスが異なるオブジェクトを見つけようとすると、in_array
直観に反する動作を示します。
PHP.netには、直感に反するエッジ ケースに関する素晴らしいユーザー コメントがあります。
// Example array $array = array( 'egg' => true, 'cheese' => false, 'hair' => 765, 'goblins' => null, 'ogres' => 'no ogres allowed in this array' ); // Loose checking -- return values are in comments // First three make sense, last four do not in_array(null, $array); // true in_array(false, $array); // true in_array(765, $array); // true in_array(763, $array); // true in_array('egg', $array); // true in_array('hhh', $array); // true in_array(array(), $array); // true // Strict checking in_array(null, $array, true); // true in_array(false, $array, true); // true in_array(765, $array, true); // true in_array(763, $array, true); // false in_array('egg', $array, true); // false in_array('hhh', $array, true); // false in_array(array(), $array, true); // false
ご覧のとおり、in_array
テスト 4 ~ 7 を厳密にチェックしないと意味がありません。
PHP.netから、2 つのオブジェクトが同じクラス + インスタンスからのものである場合、厳密な比較 ( ) でのみ同じであることがわかっています。2 つのオブジェクトは、同じクラスに属している場合、緩やかな比較 ( ) ですでに同じです。===
==
何が起こるかを見るために、オブジェクトを使ったいくつかのテストを書きました。
$a = new stdClass();
$a->egg = true;
$b = new stdClass();
$b->cheese = false;
$c = new stdClass();
$c->hair = 765;
$d = new stdClass();
$d->goblins = null;
$e = new stdClass();
$e->ogres = 'no ogres allowed in this array';
$array2 = array($a, $b, $c, $d, $e);
$e = new stdClass();
$e->egg = null;
$f = new stdClass();
$f->egg = false;
$g = new stdClass();
$g->egg = 765;
$h = new stdClass();
$h->egg = 763;
$i = new stdClass();
$i->egg = 'egg';
$j = new stdClass();
$j->egg = 'hhh';
$k = new stdClass();
$k->egg = array();
in_array($e, $array2, false); // false
in_array($f, $array2, false); // false
in_array($g, $array2, false); // true
in_array($h, $array2, false); // true
in_array($i, $array2, false); // true
in_array($j, $array2, false); // true
in_array($k, $array2, false); // false
in_array($e, $array2, true); // false
in_array($f, $array2, true); // false
in_array($g, $array2, true); // false
in_array($h, $array2, true); // false
in_array($i, $array2, true); // false
in_array($j, $array2, true); // false
in_array($k, $array2, true); // false
最後のチェックでは、in_array
チェック 3 ~ 6 で直観に反する結果が得られます。
その理由は以下の通りです。特定の値を持つオブジェクトを見つけようとすると、緩やかな比較を使用する必要があります (クラスが同じでない場合、厳密な比較は常に失敗するため)。しかし、PHP の変数の型により、最後のテストでは、値が真であると見なされるため、これらのチェックは真と見なされます。また、緩やかな比較ではオブジェクトのキーが無視されることに注意してください。
http://php.net/manual/en/function.spl-object-hash.phpを参照してください。
if ( ! array_key_exists( spl_object_hash( $obj ), $objects ) ) {
$objects[ spl_object_hash( $obj ) ] = $obj;
}
乾杯
新しい PHP バージョンが原因かどうかはわかりませんが、私のプロジェクトでは、Ubuntu 12.04 で PHP 5.3.16 を使用して動作しました。オブジェクトの配列に針オブジェクトが見つかりました。また、同じクラスの別のオブジェクトをロードし、そのオブジェクトを含まない配列の内容に対してテストすることで再確認しましたが、実際には false が返されました。
はい、in_array
オブジェクトを比較できます。
私はやや異なる、より堅牢なオプションを考え出しました。
function array_add_unique(&$array, $new, $test, $cb) {
if(is_array($array) && count($array)>0) {
for($i = 0; $i < count($array); $i++) {
if( $array[$i][$test] == $new[$test] ) {
$do = $cb($array[$i], $new);
if(is_bool($do) && $do) { $array[$i] = $new; }
else if(!is_bool($do)) { $array[$i] = $do; }
return;
}
}
}
array_push($array, $new);
}
このソリューションの利点は、衝突を処理するためのユーザー定義可能なコールバックが含まれていることです。一意のオブジェクトを追加する場合、古いオブジェクトと新しいオブジェクトの両方のプロパティを保持したい場合があります。
匿名関数であるコールバックは、新しいオブジェクトと既存のオブジェクトの両方を受け取るため、ユーザーはカスタム計算を行うことができます。trueを返して既存のオブジェクトを単純に置き換えるか、新しいオブジェクト (bool 以外) を返して置き換えます。
ただし、大規模なデータセットでのこれのパフォーマンスはわかりません。