PHP in_array对象比较?

时间:2013-06-21 09:33:31

标签: php

in_array函数可以比较对象吗?

例如,我有一个对象数组,我想将它们明确地添加到另一个数组中。是否可以检查是否已添加对象:

in_array($distinct, $object);

还是有其他方法吗?

8 个答案:

答案 0 :(得分:24)

您可以使用严格比较:

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); //

答案 1 :(得分:11)

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;
    }
}

答案 2 :(得分:2)

请参阅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;
}

干杯

答案 3 :(得分:2)

你可以看到很多方法可以做到这一点。我以为我会添加另一个。我不知道为什么,但在使用对象数组时,我喜欢使用使用回调的数组函数。

如果您的对象具有任何类型的标识符,如果您要测试它们以进行复制,则应该使用以下标识符:

$found = array_filter($uniqueObjects, function($uniqueObject) use ($object) {
    return $uniqueObject->id == $object->id
});

if (!$found) {
    $uniqueObjects[] = $object;
}

$object是您正在寻找的对象,而$uniqueObjects是您要搜索的对象数组,以查看它是否存在。只需在标识属性上匹配uniqueObject和object,例如id

答案 4 :(得分:1)

我不知道是不是因为更新的PHP版本,但在我的项目中,在Ubuntu 12.04上使用PHP 5.3.16,它确实有效。它在我的对象数组中找到了针对象。我还通过加载同一个类的不同对象进行双重检查,并根据不包含该对象的数组内容对其进行测试,并确实返回false。

是的,in_array可以比较对象。

答案 5 :(得分:0)

如果" STRICT"是" FALSE",通过在字符串中转换元素来进行比较。因此,如果覆盖__toString魔术函数,则应该可以比较对象元素。

答案 6 :(得分:0)

我想出了一个有点不同的,我认为更强大的选择。

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)来替换它。

我不知道在大型数据集上的表现。

答案 7 :(得分:0)

我通过比较对象与in_array函数进行了一些测试。这是我的结论:

当您尝试在数组(例如OP)中找到对象的相同实例时,in_array可以使用严格比较布尔集。

当您尝试查找具有相同实例但具有不同实例的任何对象时,in_array会显示违反直觉的行为。

关于违反直觉的边缘案例有great user comment on 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,就没有任何意义。

我们know from 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's variable types,在最后的测试中,这些检查被认为是正确的,因为该值被认为是真实的。另外请注意,在松散比较中会忽略对象上的键。