2010-05-14 102 views
9

我想知道如何array_intersect對象數組。數組相交爲對象數組php

+0

你是什麼意思的「對象數組」 - 你的意思是一個對象數組? – thetaiko 2010-05-14 13:59:53

+0

是的,那是對象數組。 – 2010-05-14 14:09:13

回答

2

array_intersect()返回包含所有參數中存在的array1的所有值的數組。

那麼究竟意味着什麼目前在這方面(exacly此功能),我發現php.net我的回答:

Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.

那麼你可以不使用它的陣列對象如果你的對象沒有實現對字符串的唯一轉換。

+4

這是無恥的。至少有三種方法可以將對象轉換爲字符串。它們可能是一個PHP類並實現__toString,它們可能有一個接受IS_STRING的轉換處理程序,它們可能有一個get處理程序,它返回一個可轉換爲字符串的zval。 – Artefacto 2010-05-14 14:01:05

+0

+1 @Artefacto,用一個使用任意對象和array_intersect()的例子來提交答案。 – Dolph 2010-05-14 14:04:33

+0

如果你的對象沒有實現對字符串的唯一轉換。 – Svisstack 2010-05-14 14:05:49

1

檢查兩個對象是否相等的正確方法是使用==。因此:

array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 == $a2; }); 
+0

這不起作用.. 你有其他編碼嗎? – 2010-05-15 12:30:40

+1

你必須更具體。什麼不行?有沒有錯誤信息?什麼錯誤信息?輸出不是預期的?預期什麼?你得到了什麼? – Artefacto 2010-05-15 19:19:21

+1

這不起作用,因爲array_unintersect需要比較函數返回1,-1或0. 請參閱此處以獲取完整說明和示例http://php.net/manual/en/function.array-uintersect。 php#72841 – Tim 2014-12-21 09:23:39

6

不錯的toString功能已經實現,被稱爲連載;)這樣

array_map(
    'unserialize', 
    array_intersect(
     array_map(
      'serialize', 
      $obj1 
     ), 
     array_map(
      'serialize', 
      $obj2 
     ) 
    ) 
); 

會做的工作,例如提到更高的不工作「導致array_intersect工作的只有字符串作爲人也提到

+0

優秀的黑客。完美的作品:) – yitwail 2012-04-07 23:30:12

+0

進一步思考,如果對象有方法,這是不夠的。當你序列化時,你失去了方法,所以只保留屬性 – yitwail 2012-04-07 23:56:04

2

前幾天有類似的問題,而這些答案都是正確的路徑;我用它們來制定出以下幾點:

從Artefacto的回答return $obj1 == $obj2並沒有真正的工作,所以我寫了一個簡單的比較功能(基本上得到序列化對象的MD5和比較了):

function object_compare($obj1, $obj2){ 
    $md5 = function($obj){ 
    return md5(serialize($obj)); 
    }; 
    return strcmp($md5($obj1), $md5($obj2)); 
} 

那麼它的突出部分調用和array_uintersect與我們的比較函數來獲取交集的問題:

# $array1/$array2 are the array of objects we want to compare 
return array_uintersect($array1, $array2, 'object_compare'); 

就我而言,我有對象的未知/動態數組,所以我把它更進了一步,所以我不要」不得不申報array_uintersect($array1, $array2, ...)特別 - 只是能在(對象)數組的數組來傳遞:

# $multiarray_of_objects is our array of arrays 
$multiarray_of_objects[] = 'object_compare'; 
return call_user_func_array('array_uintersect', $multiarray_of_objects); 

只要得記得在參考我們的回調/對比功能數組中的最後一個字符串傳遞。奇蹟般有效!

+0

由於在控制器類中工作,我不能這樣做,但使用Artefacto格式的方法像魅力一樣工作。 – Magnanimity 2014-04-02 12:46:38

+0

在類'返回array_uintersect($ array1,$ array2,'self :: object_compare');'應該工作,甚至'ClassName :: object_compare',但記住它需要是一個公共類函數。 – Atari 2017-08-18 14:59:46

0

我使用array_udiff來實現object array的array_intersect。

function diff($a, $b) { 
if($a === $b) { 
    return 0; 
} else { 
    return 1;} 
} 

$array_1 = array('a', 'b', 'c');  

$array_2 = array('c', 'd','e');  

$array = array_udiff($array_1, array_udiff($array_1, $array_2, 'diff'),'diff'); 

var_dump($array); 
return array(1) { [2]=> string(1) "c" } 

對於任何方案您都可以擁有自己的diff功能。

8

您可以結合使用和array_uintersect與spl_object_hash,看一個例子:

array_uintersect($a, $b, function($a, $b) { 
     return strcmp(spl_object_hash($a), spl_object_hash($b)); 
    }); 

其中「$ a」和「$ B」是要交一些對象的數組。

+0

很好的解決方案。對於當代讀者來說:在php7中,'strcmp()'可以用'<=>'運算符代替,如下所示:'return spl_object_hash($ a)<=> spl_object_hash($ b);' – 2017-10-03 10:41:37

-1

正確的解決辦法是:

array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 != $a2; }); 

注意=中,而不是從@Artefacto答案回調函數!基於array_uintersect的文檔,如果數組項相等,則回調函數必須返回0(假)。

+0

這是一種不必要的類型破解,如果第一個值小於,等於或大於第二個值,則回調函數應該返回整數(-1,0,1),就像排序函數一樣。隱含的0到0的類型轉換會混淆你的代碼的讀者。 – amik 2017-05-14 15:30:23

0

只是爲了完整:在您的對象中實現__toString()方法返回一個唯一值。對於數據庫實體而言,這可能與返回完全限定的類名後綴與記錄的ID一樣簡單。但是通過做一些散列或者甚至更糟糕的事情也可能是任意複雜的。

在我看來,這是班級的責任,要序列化自己或創建一些獨特的東西來比較它的對象。使用類之外的任何東西來序列化對象可能會導致奇怪的行爲(包括比較不同類的對象,這絕不會導致相等)。