वस्तुओं के लिए array_unique जैसी कोई विधि है? मेरे पास 'भूमिका' वस्तुओं के साथ सरणियों का एक गुच्छा है जिसे मैं विलय करता हूं, और फिर मैं डुप्लिकेट को बाहर निकालना चाहता हूं :)
जवाबों:
खैर, array_unique()
तत्वों के स्ट्रिंग मूल्य की तुलना करता है:
नोट : दो तत्वों को समान माना जाता है यदि और केवल अगर
(string) $elem1 === (string) $elem2
यानी जब स्ट्रिंग प्रतिनिधित्व समान है, तो पहले तत्व का उपयोग किया जाएगा।
इसलिए __toString()
अपनी कक्षा में विधि को लागू करना सुनिश्चित करें और यह समान भूमिकाओं के लिए समान मूल्य का उत्पादन करता है, जैसे
class Role {
private $name;
//.....
public function __toString() {
return $this->name;
}
}
यह दो भूमिकाओं को समान मानता है यदि उनका नाम समान है।
array_unique
है और न ही __toString()
तुलना में कुछ भी। __toString()
परिभाषित करता है कि किसी स्ट्रिंग संदर्भ में उपयोग किए जाने पर ऑब्जेक्ट का उदाहरण कैसे माना जाता है और array_unique
हटाए गए डुप्लिकेट मानों के साथ इनपुट सरणी देता है। यह सिर्फ आंतरिक रूप से इसके लिए तुलना का उपयोग करता है ।
echo $object
भी __toString
विधि का उपयोग करता है ।
__toString()
अपनी सभी वस्तुओं के तरीकों को जोड़ना बहुत अधिक दर्दनाक है फिर बस SORT_REGULAR
array_unique में एक ध्वज जोड़ना, मैथ्यू नपोली का जवाब देखें। एक __toString()
विधि के अलावा कई अन्य उपयोग के मामले हैं तो वस्तु तुलना के लिए उपयोग किया जा रहा है, इसलिए यह भी संभव नहीं हो सकता है।
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
चेतावनी : यह "==" तुलना का उपयोग करेगा, न कि सख्त तुलना ("===") का।
इसलिए यदि आप वस्तुओं की एक सरणी के अंदर डुप्लिकेट को निकालना चाहते हैं, तो सावधान रहें कि यह प्रत्येक वस्तु गुणों की तुलना करेगा, वस्तु पहचान (उदाहरण) की तुलना नहीं करेगा।
==
) या पहचान ( ===
) के अंतर की तुलना के बीच का अंतर नहीं दिखाता (अंतर दिखाने के लिए $bam->prop = 'test2';
होना चाहिए 'test1'
)। एक उदाहरण के लिए codepad.viper-7.com/8NxWhG देखें ।
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);
in_array
$strict
पैरामीटर का उपयोग करना चाहिए ! इसके बजाय आप "===" के बजाय "==" का उपयोग करके वस्तुओं की तुलना करते हैं। यहाँ और अधिक: fr2.php.net/manual/fr/function.in-array.php
यहाँ एक सरणी में डुप्लिकेट की गई वस्तुओं को हटाने का एक तरीका है:
<?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);
यदि आप किसी विशिष्ट विशेषता के आधार पर वस्तुओं को फ़िल्टर करना चाहते हैं, तो आप 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;
});
यहां से: 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);
}
?>
यदि आपके पास ऑब्जेक्ट्स का अनुक्रमित सरणी है, और आप प्रत्येक ऑब्जेक्ट में एक विशिष्ट संपत्ति की तुलना करके डुप्लिकेट को निकालना चाहते हैं, तो 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
)
)
अगर आप डुप्लिकेट किए गए इंस्टेंस (यानी "===" तुलना) को फ़िल्टर करना चाहते हैं, तो तेज़ और तेज़ तरीका:
है:
//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
यह बहुत ही सरल उपाय है:
$ids = array();
foreach ($relate->posts as $key => $value) {
if (!empty($ids[$value->ID])) { unset($relate->posts[$key]); }
else{ $ids[$value->ID] = 1; }
}
array_unique तत्वों को स्ट्रिंग से जोड़कर और तुलना करके काम करता है। जब तक आपकी वस्तुओं को विशिष्ट रूप से तार में नहीं डाला जाता है, तब तक वे array_unique के साथ काम नहीं करेंगे।
इसके बजाय, अपनी वस्तुओं के लिए एक स्टेटफुल तुलनात्मक फ़ंक्शन को लागू करें और फ़ंक्शन पहले से देखी गई चीज़ों को फेंकने के लिए array_filter का उपयोग करें ।
array_unique
SORT_REGULAR काम करता है, नीचे मेरा जवाब देखें।
यह सरल गुणों के साथ वस्तुओं की तुलना करने का मेरा तरीका है, और एक ही समय में एक अनूठा संग्रह प्राप्त करना है:
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)
यदि आपके पास ऑब्जेक्ट्स की सरणी है और आप सभी डुप्लिकेट को हटाने के लिए इस संग्रह को फ़िल्टर करना चाहते हैं, तो आप गुमनाम फ़ंक्शन के साथ 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
कॉलबैक फ़ंक्शन को संदर्भित करने के लिए सरणी को पास करना होगा अन्यथा यह काम नहीं करेगा