有没有像array_unique这样的对象方法?我有一堆合并了“角色”对象的数组,然后我想取出重复项:)
Answers:
好吧,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添加标志要痛苦得多,请参阅Matthieu Napoli他的回答。此外,__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。
之所以使用此答案,是in_array()
因为PHP 5中比较对象的性质允许我们这样做。利用此对象比较行为需要数组仅包含对象,但在这里似乎是这种情况。
$merged = array_merge($arr, $arr2);
$final = array();
foreach ($merged as $current) {
if ( ! in_array($current, $final)) {
$final[] = $current;
}
}
var_dump($final);
这是一种删除数组中重复对象的方法:
<?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/zh/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
数组作为对过滤器回调函数的引用进行传递,否则它将不起作用