对象的 array_unique ?

发布于 2024-10-08 18:16:43 字数 66 浏览 3 评论 0原文

是否有类似对象的 array_unique 的方法?我有一堆带有“角色”对象的数组,我将其合并,然后我想取出重复项:)

Is there any method like the array_unique for objects? I have a bunch of arrays with 'Role' objects that I merge, and then I want to take out the duplicates :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

终陌 2024-10-15 18:16:43

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

警告:它将使用“==”比较,而不是严格比较(“===”)。

因此,如果您想删除对象数组中的重复项,请注意它将比较每个对象属性,而不是比较对象标识(实例)。

array_unique works with an array of objects using 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));

Will print:

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

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

See it in action here: http://3v4l.org/VvonH#v529

Warning: it will use the "==" comparison, not the strict comparison ("===").

So if you want to remove duplicates inside an array of objects, beware that it will compare each object properties, not compare object identity (instance).

你曾走过我的故事 2024-10-15 18:16:43

好吧, array_unique() 比较字符串元素的值:

注意:当且仅当 (string) $elem1 === (string) $elem2 即当字符串表示形式相同时,两个元素被视为相等,将使用第一个元素。

因此,请确保实现 __toString() 方法在您的类中,并且它为相同的角色输出相同的值,例如,

class Role {
    private $name;

    //.....

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

}

如果两个角色具有相同的名称,则这会将它们视为相同。

Well, array_unique() compares the string value of the elements:

Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2 i.e. when the string representation is the same, the first element will be used.

So make sure to implement the __toString() method in your class and that it outputs the same value for equal roles, e.g.

class Role {
    private $name;

    //.....

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

}

This would consider two roles as equal if they have the same name.

新人笑 2024-10-15 18:16:43

由于 PHP 中比较对象的本质,此答案使用 in_array() 5 允许我们这样做。利用此对象比较行为要求数组包含对象,但这里似乎就是这种情况。

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

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

var_dump($final);

This answer uses in_array() since the nature of comparing objects in PHP 5 allows us to do so. Making use of this object comparison behaviour requires that the array only contain objects, but that appears to be the case here.

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

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

var_dump($final);
燃情 2024-10-15 18:16:43

以下是删除数组中重复对象的方法:

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

Here is a way to remove duplicated objects in an array:

<?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);
不气馁 2024-10-15 18:16:43

您也可以先序列化:

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

从 PHP 5.2.9 开始,您可以仅使用可选的 sort_flag SORT_REGULAR

$unique = array_unique( $array, SORT_REGULAR );

You can also serialize first:

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

As of PHP 5.2.9 you can just use optional sort_flag SORT_REGULAR:

$unique = array_unique( $array, SORT_REGULAR );
二货你真萌 2024-10-15 18:16:43

如果您想根据特定属性过滤对象,还可以使用 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;
});

You can also use they array_filter function, if you want to filter objects based on a specific attribute:

//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;
});
宛菡 2024-10-15 18:16:43

从这里: 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);
}
?>

From here: http://php.net/manual/en/function.array-unique.php#75307

This one would work with objects and arrays also.

<?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);
}
?>
合约呢 2024-10-15 18:16:43

如果您需要从数组中过滤重复的实例(即“===”比较)并且:

  • 您确定哪个数组仅保存
  • 您不需要保留键

的对象,那么明智且快速的方法是:

//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

sane and fast way if you need to filter duplicated instances (i.e. "===" comparison) out of array and:

  • you are sure what array holds only objects
  • you dont need keys preserved

is:

//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
樱&纷飞 2024-10-15 18:16:43

如果您有一个对象的索引数组,并且想要通过比较每个对象中的特定属性来删除重复项,则可以使用类似下面的 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
        )

)

If you have an indexed array of objects, and you want to remove duplicates by comparing a specific property in each object, a function like the remove_duplicate_models() one below can be used.

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

The result is:

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

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

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

)
半城柳色半声笛 2024-10-15 18:16:43

这是非常简单的解决方案:

$ids = array();

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

This is very simple solution:

$ids = array();

foreach ($relate->posts as $key => $value) {
  if (!empty($ids[$value->ID])) { unset($relate->posts[$key]); }
  else{ $ids[$value->ID] = 1; }
}
鸠魁 2024-10-15 18:16:43

您还可以使用回调函数使数组唯一(例如,如果您想比较对象的属性或任何方法)。

这是我用于此目的的通用函数:

/**
* 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();
    }
);

You can also make the array unique using a callback function (e.g. if you want to compare a property of the object or whatever method).

This is the generic function I use for this purpose:

/**
* 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);
}

Sample usage:

$myUniqueArray = unique($arrayToFilter,
    static function (ExamQuestion $examQuestion) {
        return $examQuestion->getId();
    }
);
焚却相思 2024-10-15 18:16:43

用于严格 (===) 比较的array_unique 版本,保留键:

function array_unique_strict(array $array): array {
    $result = [];
    foreach ($array as $key => $item) {
        if (!in_array($item, $result, true)) {
            $result[$key] = $item;
        }
    }
    return $result;
}

用法:

class Foo {}
$foo1 = new Foo();
$foo2 = new Foo();
array_unique_strict( ['a' => $foo1, 'b' => $foo1, 'c' => $foo2] ); // ['a' => $foo1, 'c' => $foo2]

array_unique version for strict (===) comparison, preserving keys:

function array_unique_strict(array $array): array {
    $result = [];
    foreach ($array as $key => $item) {
        if (!in_array($item, $result, true)) {
            $result[$key] = $item;
        }
    }
    return $result;
}

Usage:

class Foo {}
$foo1 = new Foo();
$foo2 = new Foo();
array_unique_strict( ['a' => $foo1, 'b' => $foo1, 'c' => $foo2] ); // ['a' => $foo1, 'c' => $foo2]
人间☆小暴躁 2024-10-15 18:16:43

array_unique 的工作原理是将元素转换为字符串并进行比较。除非您的对象唯一地转换为字符串,否则它们将无法与 array_unique 一起使用。

相反,为您的对象实现有状态比较函数并使用 array_filter扔掉函数已经看到的东西。

array_unique works by casting the elements to a string and doing a comparison. Unless your objects uniquely cast to strings, then they won't work with array_unique.

Instead, implement a stateful comparison function for your objects and use array_filter to throw out things the function has already seen.

无风消散 2024-10-15 18:16:43

这是我比较具有简单属性的对象的方式,同时接收唯一的集合:

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)

This is my way of comparing objects with simple properties, and at the same time receiving a unique collection:

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

Will output:

array (size=2)
  'foo' => 
    object(Role)[1165]
      private 'name' => string 'foo' (length=3)
  'bar' => 
    object(Role)[1166]
      private 'name' => string 'bar' (length=3)
硪扪都還晓 2024-10-15 18:16:43

如果您有对象数组并且想要过滤此集合以删除所有重复项,您可以将 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 数组传递为引用你的过滤器回调函数,否则它将不起作用

If you have array of objects and you want to filter this collection to remove all duplicates you can use array_filter with anonymous function:

$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;
});

Important: Remember that you must pass $tmp array as reference to you filter callback function otherwise it will not work

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文