有没有像array_unique一样的方法可以用于对象?我有一堆包含“Role”对象的数组,我需要将它们合并,然后去除重复的元素 :)
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'
来展示差异)。请参考http://codepad.viper-7.com/8NxWhG的示例。 - Flipprivate, protected, public
)的字段上工作吗? - james好的,array_unique()
函数比较元素的字符串值:
注意:仅当
(string)$elem1 === (string)$elem2
时,两个元素被视为相等,即当字符串表示相同时,将使用第一个元素。
因此,请确保在您的类中实现__toString()
方法,并且它输出相同的值来代表相等的角色,例如:
class Role {
private $name;
//.....
public function __toString() {
return $this->name;
}
}
如果两个角色具有相同的名称,则认为它们是相等的。
array_unique
和__toString()
都没有进行任何比较。__toString()
定义了对象实例在字符串上下文中的行为方式,而array_unique
返回已删除重复值的输入数组。它只是在内部使用比较。 - Gordonecho $object
也使用了__toString
方法。 - Felix Kling__toString()
方法添加到您的所有对象中比仅将SORT_REGULAR
标志添加到array_unique
要麻烦得多,参见Matthieu Napoli的答案。此外,__toString()
方法有许多其他用途,而不仅仅是用于对象比较,因此这可能甚至不可行。 - Flip由于 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
参数!否则,您将使用 "==" 而不是 "===" 来比较对象。更多信息请参见:http://fr2.php.net/manual/fr/function.in-array.php - Matthieu Napoli以下是一种从数组中删除重复对象的方法:
<?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);
您也可以先进行序列化:
$unique = array_map( 'unserialize', array_unique( array_map( 'serialize', $array ) ) );
从 PHP 5.2.9 开始,您可以直接使用可选的 sort_flag SORT_REGULAR
:
$unique = array_unique( $array, SORT_REGULAR );
如果您想根据特定属性过滤对象,也可以使用they 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);
}
?>
如果您需要从数组中过滤重复的实例(即“ ===”比较),并且:
那么最好的方法是:
//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
如果您有一个对象的索引数组,并且想要通过比较每个对象中的特定属性来删除重复项,则可以使用下面类似于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
)
)
/**
* Remove duplicate elements from an array by comparison callback.
*
* @param array $array : An array to eliminate duplicates by callback
* @param callable $callback : Callback accepting an array element returning the value to compare.
* @param bool $preserveKeys : Add true if the keys should be perserved (note that if duplicates eliminated the first key is used).
* @return array: An array unique by the given callback
*/
function unique(array $array, callable $callback, bool $preserveKeys = false): array
{
$unique = array_intersect_key($array, array_unique(array_map($callback, $array)));
return ($preserveKeys) ? $unique : array_values($unique);
}
使用示例:
$myUniqueArray = unique($arrayToFilter,
static function (ExamQuestion $examQuestion) {
return $examQuestion->getId();
}
);