Может ли функция in_array
сравнивать объекты?
Например, у меня есть массив объектов, и я хочу добавить их к другому массиву. Можно ли проверить, был ли объект уже добавлен так:
in_array($distinct, $object);
или есть ли другой способ?
Может ли функция in_array
сравнивать объекты?
Например, у меня есть массив объектов, и я хочу добавить их к другому массиву. Можно ли проверить, был ли объект уже добавлен так:
in_array($distinct, $object);
или есть ли другой способ?
Функция in_array не может сравнивать объекты.
Вам необходимо создать уникальные пары ключ-значение из ваших объектов и только сравнить эти ключи при вставке нового объекта в ваш окончательный массив.
Предполагая, что каждый объект имеет уникальное свойство id
, возможным решением будет следующее:
$unique_objects = array();
// $data represents your object collection
foreach ($data as $item) {
if (!array_key_exists($item->id, $unique_objects)) {
$unique_objects[$item->id] = $obj;
}
}
Вы можете использовать строгое сравнение:
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); //
См. 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;
}
Приветствия
Существует множество способов сделать это, как вы можете видеть. Я просто подумал, что добавлю еще один. Я не знаю почему, но при работе с объектными массивами мне нравится использовать функции массива, которые используют обратные вызовы.
Если у ваших объектов есть какой-либо идентификатор, который они должны, если вы хотите проверить их для дублирования, будет работать следующее:
$found = array_filter($uniqueObjects, function($uniqueObject) use ($object) {
return $uniqueObject->id == $object->id
});
if (!$found) {
$uniqueObjects[] = $object;
}
$object
- объект, который вы ищете, и $uniqueObjects
- это массив объектов, которые вы ищете, чтобы увидеть, существует ли он. Просто сопоставьте uniqueObject и объект с идентификационным свойством, например id
.
Я не знаю, связано ли это с новой версией PHP, но в моем проекте, используя PHP 5.3.16 на Ubuntu 12.04, это сработало. Он нашел объект иглы в моем массиве объектов. Я также дважды проверял загрузку другого объекта того же класса и тестирование его на содержимое массива, которое не содержало этот объект, и оно действительно верно вернулось.
Итак, да, in_array
может сравнивать объекты.
Если "STRICT" является "FALSE", сравнение производится путем преобразования в строку элементов. Поэтому, если вы переопределите магическую функцию __toString, вы должны быть доступны для сравнения элементов объектов.
Я придумал несколько другое, я думаю, более надежный вариант.
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, чтобы просто заменить существующий объект или вернуть новый объект (non-bool), чтобы заменить его.
Я не знаю, как это работает на больших наборах данных.
Я провел несколько тестов со сравнением объектов с помощью функции 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
не имеют смысла.
Мы знаем из PHP.net, что два объекта одинаковы при строгом сравнении (===
), если они принадлежат одному и тому же классу + экземпляру. Два объекта уже одинаковы в произвольном сравнении (==
), когда они принадлежат к одному и тому же классу.
Я написал несколько тестов с объектами, чтобы увидеть, что происходит.
$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 в последних тестах эти проверки считаются истинными, потому что значение считается истинным. Также обратите внимание, что ключ на объекте игнорируется при произвольном сравнении.