array_unique ऑब्जेक्ट्स के लिए?


84

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


जवाबों:


98

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

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

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

class Role {
    private $name;

    //.....

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

}

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


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

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

3
__toString()अपनी सभी वस्तुओं के तरीकों को जोड़ना बहुत अधिक दर्दनाक है फिर बस SORT_REGULARarray_unique में एक ध्वज जोड़ना, मैथ्यू नपोली का जवाब देखें। एक __toString()विधि के अलावा कई अन्य उपयोग के मामले हैं तो वस्तु तुलना के लिए उपयोग किया जा रहा है, इसलिए यह भी संभव नहीं हो सकता है।
फ्लिप करें

156

array_uniqueवस्तुओं के एक सरणी के साथ काम करता है 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

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

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


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

@vishal के आधिकारिक दस्तावेज़ीकरण पर एक नज़र: php.net/manual/en/function.array-unique.php
Matthieu Napoli

1
आपने मुझे भाई, TnQ को बहुत सहेजा: *
समन सत्तारी

1
स्वीकृत उत्तर होना चाहिए। इसके अलावा यह __toString () का उपयोग करने से बहुत तेज है। तुलना परिणाम के लिए देखें: sandbox.onlinephpfunctions.com/code/…
लुकाएम

1
Array_unique () के साथ ऑब्जेक्ट्स की तुलना करते हुए देखें, फ़ंक्शन एक गहरी तुलना लागू करेगा, जिसके परिणामस्वरूप आपका सर्वर क्रैश हो सकता है यदि इसमें बहुत अधिक पुनरावृत्ति शामिल है - मैं आपको Doctrine संस्थाओं को देख रहा हूं। बेहतर पहचानें जो आपकी वस्तु को अद्वितीय बनाती है और आपकी वस्तुओं को इसके साथ अनुक्रमित करती है। उदाहरण के लिए, यदि आपकी वस्तुओं में स्ट्रिंग पहचानकर्ता है, तो कुंजी के रूप में उस पहचानकर्ता के साथ एक सरणी बनाएं।
ऑल्वेल्व

31

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

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

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

var_dump($final);

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

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

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

1
सख्त पैरामीटर का उपयोग नहीं करना यहां एक जानबूझकर पसंद था। मैं "समान" वस्तुओं को ढूंढना चाहता था, जरूरी नहीं कि किसी वस्तु का एक ही उदाहरण हो । यह उत्तर में उल्लिखित लिंक में समझाया गया है, जो कहता है, " तुलना ऑपरेटर (==) का उपयोग करते समय, ऑब्जेक्ट चर की तुलना एक सरल तरीके से की जाती है, अर्थात्: दो ऑब्जेक्ट उदाहरण समान होते हैं यदि उनके समान गुण और मान हों, और उसी वर्ग के उदाहरण हैं। "
सलातो

एक जादू की तरह काम करता है! बहुत बहुत धन्यवाद
gronaz

17

यहाँ एक सरणी में डुप्लिकेट की गई वस्तुओं को हटाने का एक तरीका है:

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

यह मेरे लिए सबसे अच्छा समाधान है! मैं अपनी वेबसाइट के लिए इस समाधान का उपयोग कर रहा हूँ खोज (एक डेटाबेस से 2 क्वेरीज़ मर्ज)। पहले मेरे पास सभी खोजकर्ताओं के लिए resuls है, और मैं उन्हें कुछ खोजकर्ताओं के परिणामों के साथ मिला देता हूं। इस समाधान के साथ मेरे पास सबसे महत्वपूर्ण परिणाम हैं पहले, अद्वितीय अन्य समाधानों द्वारा जोड़ा गया ..
फाइंडुइलास

11

आप पहले भी धारावाहिक कर सकते हैं:

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

PHP 5.2.9 के अनुसार आप केवल वैकल्पिक का उपयोग कर सकते हैं sort_flag SORT_REGULAR:

$unique = array_unique( $array, SORT_REGULAR );

9

यदि आप किसी विशिष्ट विशेषता के आधार पर वस्तुओं को फ़िल्टर करना चाहते हैं, तो आप 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;
});

6

यहां से: 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);
}
?>

2

यदि आपके पास ऑब्जेक्ट्स का अनुक्रमित सरणी है, और आप प्रत्येक ऑब्जेक्ट में एक विशिष्ट संपत्ति की तुलना करके डुप्लिकेट को निकालना चाहते हैं, तो remove_duplicate_models()नीचे दिए गए फ़ंक्शन का उपयोग किया जा सकता है।

class Car {
    private $model;

    public function __construct( $model ) {
        $this->model = $model;
    }

    public function get_model() {
        return $this->model;
    }
}

$cars = [
    new Car('Mustang'),
    new Car('F-150'),
    new Car('Mustang'),
    new Car('Taurus'),
];

function remove_duplicate_models( $cars ) {
    $models = array_map( function( $car ) {
        return $car->get_model();
    }, $cars );

    $unique_models = array_unique( $models );

    return array_values( array_intersect_key( $cars, $unique_models ) );
}

print_r( remove_duplicate_models( $cars ) );

परिणाम है:

Array
(
    [0] => Car Object
        (
            [model:Car:private] => Mustang
        )

    [1] => Car Object
        (
            [model:Car:private] => F-150
        )

    [2] => Car Object
        (
            [model:Car:private] => Taurus
        )

)

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

0

यह बहुत ही सरल उपाय है:

$ids = array();

foreach ($relate->posts as $key => $value) {
  if (!empty($ids[$value->ID])) { unset($relate->posts[$key]); }
  else{ $ids[$value->ID] = 1; }
}

-1

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

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


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

1
array_uniqueSORT_REGULAR काम करता है, नीचे मेरा जवाब देखें।
मैथ्यू नेपोली

-1

यह सरल गुणों के साथ वस्तुओं की तुलना करने का मेरा तरीका है, और एक ही समय में एक अनूठा संग्रह प्राप्त करना है:

class Role {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

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

$roles = [
    new Role('foo'),
    new Role('bar'),
    new Role('foo'),
    new Role('bar'),
    new Role('foo'),
    new Role('bar'),
];

$roles = array_map(function (Role $role) {
    return ['key' => $role->getName(), 'val' => $role];
}, $roles);

$roles = array_column($roles, 'val', 'key');

var_dump($roles);

उत्पादन होगा:

array (size=2)
  'foo' => 
    object(Role)[1165]
      private 'name' => string 'foo' (length=3)
  'bar' => 
    object(Role)[1166]
      private 'name' => string 'bar' (length=3)

-1

यदि आपके पास ऑब्जेक्ट्स की सरणी है और आप सभी डुप्लिकेट को हटाने के लिए इस संग्रह को फ़िल्टर करना चाहते हैं, तो आप गुमनाम फ़ंक्शन के साथ array_filter का उपयोग कर सकते हैं:

$myArrayOfObjects = $myCustomService->getArrayOfObjects();

// This is temporary array
$tmp = [];
$arrayWithoutDuplicates = array_filter($myArrayOfObjects, function ($object) use (&$tmp) {
    if (!in_array($object->getUniqueValue(), $tmp)) {
        $tmp[] = $object->getUniqueValue();
        return true;
    }
    return false;
});

महत्वपूर्ण: याद रखें कि आपको $tmpकॉलबैक फ़ंक्शन को संदर्भित करने के लिए सरणी को पास करना होगा अन्यथा यह काम नहीं करेगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.