2010-03-11 11 views
55

क्या वस्तुओं के लिए array_unique जैसी कोई विधि है? मैं 'भूमिका' वस्तुओं है कि मैं विलय के साथ सरणियों का एक समूह है, और फिर मैं डुप्लिकेट :)array_unique?

+1

की डुप्लीकेट http://stackoverflow.com/questions/1050709/how-can-i-remove-duplicates-in-an-object-array-in-php/ –

उत्तर

73

खैर बाहर करना चाहते हैं, array_unique() तत्वों की स्ट्रिंग मान तुलना:

नोट : दो तत्वों को बराबर माना जाता है यदि केवल और (string) $elem1 === (string) $elem2 यानी जब स्ट्रिंग का प्रतिनिधित्व समान होता है, तो पहला तत्व उपयोग किया जाएगा।

तो अपनी कक्षा में __toString() विधि को लागू करना सुनिश्चित करें और यह समान भूमिकाओं के लिए समान मान को आउटपुट करता है, उदा।

class Role { 
    private $name; 

    //..... 

    public function __toString() { 
     return $this->name; 
    } 

} 

यह दो भूमिकाओं के समान होगा यदि उनके पास समान नाम है।

+0

धन्यवाद =) ऐसा लगता है कि मेरे लिए बस ठीक काम करता है;) – Johannes

+2

@ जैकोब क्योंकि न तो 'array_unique' और न ही '__toString()' कुछ भी तुलना करें। '__toString() 'परिभाषित करता है कि स्ट्रिंग संदर्भ में उपयोग किए जाने पर ऑब्जेक्ट आवृत्ति का व्यवहार कैसे किया जाता है और' array_unique' इनपुट सरणी को डुप्लिकेट मानों के साथ हटा देता है। यह सिर्फ * आंतरिक रूप से इसके लिए * तुलना करता है। – Gordon

+1

@ जैकोब रिलिकिन: यह तुलनित्र नहीं है। यह वस्तु का स्ट्रिंग प्रतिनिधित्व है। मुझे लगता है कि वे इसका उपयोग करते हैं क्योंकि आप किसी भी प्रकार, ऑब्जेक्ट इत्यादि को एक स्ट्रिंग में परिवर्तित कर सकते हैं। लेकिन किसी ऑब्जेक्ट पर स्वयं स्ट्रिंग विधि न केवल इस फ़ंक्शन द्वारा उपयोग की जाती है। जैसे 'echo $ ऑब्जेक्ट 'भी' __toString' विधि का उपयोग करता है। –

5

यहाँ से: http://php.net/manual/en/function.array-unique.php#75307

यह एक वस्तुओं और सरणियों भी साथ काम करेंगे।

<?php 
function my_array_unique($array, $keep_key_assoc = false) 
{ 
    $duplicate_keys = array(); 
    $tmp   = array();  

    foreach ($array as $key=>$val) 
    { 
     // convert objects to arrays, in_array() does not support objects 
     if (is_object($val)) 
      $val = (array)$val; 

     if (!in_array($val, $tmp)) 
      $tmp[] = $val; 
     else 
      $duplicate_keys[] = $key; 
    } 

    foreach ($duplicate_keys as $key) 
     unset($array[$key]); 

    return $keep_key_assoc ? $array : array_values($array); 
} 
?> 
+0

बहुत बहुत धन्यवाद। –

+0

@ रिचर्ड नूप, आपका स्वागत है, शुभकामनाएँ! –

+0

उस पोस्ट के लिए आपको बहुत धन्यवाद @ सिल्वरलाइट इस प्रयास के लिए वोट दिया धन्यवाद एक और समय – Amjad

22

मुझे पता है कि पहले से ही एक स्वीकार्य उत्तर है, लेकिन यहां एक विकल्प है।

पिछले उत्तर के विपरीत, यह in_array() का उपयोग करता है क्योंकि PHP 5 में comparing objects की प्रकृति हमें ऐसा करने की अनुमति देती है। इस ऑब्जेक्ट तुलना व्यवहार के उपयोग के लिए आवश्यक है कि सरणी केवल में ऑब्जेक्ट्स हों, लेकिन ऐसा लगता है कि यह मामला है।

$merged = array_merge($arr, $arr2); 
$final = array(); 

foreach ($merged as $current) { 
    if (! in_array($current, $final)) { 
     $final[] = $current; 
    } 
} 

var_dump($final); 
+1

अच्छा काम करता है, यह दूसरे की तुलना में तेज़ हो सकता है (वास्तव में नहीं पता) लेकिन मैं आपका उपयोग करूंगा क्योंकि मुझे अतिरिक्त नहीं करना है इसके लिए कार्य: डी – Gigala

+0

वस्तुओं की तुलना करते समय उनके पास समान मात्रा में फ़ील्ड होना चाहिए और समान कुंजी/मान जोड़े होना चाहिए जो समान सही मानते हैं? मुझे क्या मिल रहा है .... अगर मेरे पास 2 ऑब्जेक्ट्स हैं और उनमें से एक में एक अतिरिक्त फ़ील्ड है तो उन ऑब्जेक्ट को "समान" नहीं माना जाएगा – ChuckKelly

+1

'in_array'' $ सख्त 'पैरामीटर का उपयोग करना चाहिए! अन्यथा आप "===" के बजाय "==" का उपयोग करके वस्तुओं की तुलना कर रहे हैं। यहां और अधिक: http://fr2.php.net/manual/fr/function.in-array.php –

-1

array_unique तत्वों को एक स्ट्रिंग में कास्टिंग करके और तुलना करने के द्वारा काम करता है। जब तक आपकी ऑब्जेक्ट विशिष्ट रूप से तारों पर नहीं डाली जाती, तब तक वे array_unique के साथ काम नहीं करेंगे।

इसके बजाय, अपनी ऑब्जेक्ट्स के लिए एक राज्य तुलनात्मक तुलना फ़ंक्शन लागू करें और array_filter का उपयोग करें जो फ़ंक्शन पहले से ही देखे गए हैं।

<?php 
// Here is the array that you want to clean of duplicate elements. 
$array = getLotsOfObjects(); 

// Create a temporary array that will not contain any duplicate elements 
$new = array(); 

// Loop through all elements. serialize() is a string that will contain all properties 
// of the object and thus two objects with the same contents will have the same 
// serialized string. When a new element is added to the $new array that has the same 
// serialized value as the current one, then the old value will be overridden. 
foreach($array as $value) { 
    $new[serialize($value)] = $value; 
} 

// Now $array contains all objects just once with their serialized version as string. 
// We don't care about the serialized version and just extract the values. 
$array = array_values($new); 
+0

मैं एक और अधिक सुरुचिपूर्ण समाधान के लिए hopping था (एक जिसे कॉलबैक की आवश्यकता नहीं होगी)। फिर भी, अपने उत्तर की सराहना करते हैं। –

+1

'array_unique' SORT_REGULAR कार्यों के साथ उपयोग किया जाता है, नीचे मेरा उत्तर देखें। –

10

यहाँ एक सरणी में डुप्लिकेट किए गए वस्तुओं को हटाने के लिए एक रास्ता है।SORT_REGULAR का उपयोग कर ऑब्जेक्ट की श्रृंखला के साथ

$unique = array_unique($array, SORT_REGULAR); 
+1

यहां का जवाब एक महान है और यह उन वस्तुओं के लिए समाधान प्रदान करता है जो कस्टम कक्षाओं के उदाहरण हैं लेकिन मुझे नहीं लगता कि यह बुनियादी stdClass उदाहरणों के लिए कैसे काम कर सकता है। –

+0

@Emanuil: सच है। मैंने अपने जवाब का एक और जवाब जोड़ा। – yankee

+0

क्या आप इस कोड पर कुछ टिप्पणियां जोड़ सकते हैं? मुझे नहीं लगता कि मुझे यह मिल गया है। –

6

तुम भी पहले क्रमानुसार कर सकते हैं::

$unique = array_map('unserialize', array_unique(array_map('serialize', $array))); 

पीएचपी 5.2 के रूप में

111

array_unique काम करता है: 9 तुम सिर्फ वैकल्पिक sort_flag SORT_REGULAR उपयोग कर सकते हैं

class MyClass { 
    public $prop; 
} 

$foo = new MyClass(); 
$foo->prop = 'test1'; 

$bar = $foo; 

$bam = new MyClass(); 
$bam->prop = 'test2'; 

$test = array($foo, $bar, $bam); 

print_r(array_unique($test, SORT_REGULAR)); 

प्रिंट होगा:

Array (
    [0] => MyClass Object 
     (
      [prop] => test1 
     ) 

    [2] => MyClass Object 
     (
      [prop] => test2 
     ) 
) 

यह देखें कार्रवाई यहाँ: http://3v4l.org/VvonH#v529

चेतावनी: यह "==" तुलना का उपयोग करेगा, सख्त तुलना ("===") नहीं।

तो यदि आप ऑब्जेक्ट्स की सरणी के अंदर डुप्लिकेट को हटाना चाहते हैं, तो सावधान रहें कि यह प्रत्येक ऑब्जेक्ट गुणों की तुलना करेगा, ऑब्जेक्ट पहचान (उदाहरण) की तुलना नहीं करेगा।

+9

यह उत्तर स्वीकार किए गए उत्तर के बाद बहुत बेहतर है। हालांकि उदाहरण '$ bam-> prop = 'test2' की वजह से मूल्य (' == ') या पहचान (' === ') की तुलना के बीच अंतर नहीं दिखाता है;' ('test1' होना चाहिए अंतर दिखाने के लिए)। उदाहरण के लिए http://codepad.viper-7.com/8NxWhG देखें। – Flip

+1

@ फ्लिप सहमत। यह जवाब बहुत बेहतर है। Upvoted। – MikeSchinkel

+0

कमाल .... :) ऑब्जेक्ट सरणी और सामान्य सरणी के लिए इन सभी चीजों का अध्ययन कैसे करें? – Vishal

5

तुम भी उपयोग कर सकते हैं वे समारोह array_filter, यदि आप एक विशिष्ट विशेषता के आधार पर वस्तुओं फ़िल्टर करना चाहते हैं:

//filter duplicate objects 
$collection = array_filter($collection, function($obj) 
{ 
    static $idList = array(); 
    if(in_array($obj->getId(),$idList)) { 
     return false; 
    } 
    $idList []= $obj->getId(); 
    return true; 
}); 
0

समझदार और तेज़ तरीका अगर आप डुप्लिकेट किए गए उदाहरणों फिल्टर करने के लिए की जरूरत है (यानी "===" तुलना) सरणी के बाहर और:

  • क्या आप वाकई क्या सरणी केवल वस्तुओं धारण कर रहे हैं
  • आप न की जरूरत है कुंजी संरक्षित

है:

//sample data 
$o1 = new stdClass; 
$o2 = new stdClass; 
$arr = [$o1,$o1,$o2]; 

//algorithm 
$unique = []; 
foreach($arr as $o){ 
    $unique[spl_object_hash($o)]=$o; 
} 
$unique = array_values($unique);//optional - use if you want integer keys on output