developer tip

객체에 대한 array_unique?

optionbox 2020. 10. 25. 12:07
반응형

객체에 대한 array_unique?


객체에 대한 array_unique와 같은 방법이 있습니까? 병합하는 '역할'개체가있는 배열이 많이 있고 중복 항목을 제거하고 싶습니다. :)


음, array_unique()요소의 문자열 값을 비교합니다.

참고 : (string) $elem1 === (string) $elem2문자열 표현이 동일한 경우에만 두 요소가 동일한 것으로 간주 됩니다. 첫 번째 요소가 사용됩니다.

따라서 __toString()클래스 에서 메소드 를 구현하고 동일한 역할에 대해 동일한 값을 출력 하는지 확인하십시오.

class Role {
    private $name;

    //.....

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

}

이름이 같은 경우 두 역할을 동일한 것으로 간주합니다.


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

경고 : 엄격한 비교 ( "===")가 아닌 "=="비교를 사용합니다.

따라서 객체 배열 내의 중복을 제거하려면 객체 ID (인스턴스)를 비교하지 않고 각 객체 속성을 비교한다는 점에 유의하십시오.


이 대답은 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);

배열에서 중복 된 객체를 제거하는 방법은 다음과 같습니다.

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

특정 속성을 기반으로 객체를 필터링하려는 경우 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
        )

)

배열에서 중복 된 인스턴스 (예 : "==="비교)를 필터링해야하는 경우 정확하고 빠른 방법입니다.

  • 어떤 배열이 객체만을 보유하는지 확신합니다.
  • 당신은 보존 된 키가 필요하지 않습니다

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

이것은 객체를 간단한 속성과 비교하는 동시에 고유 한 컬렉션을받는 방법입니다.

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

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


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.

참고URL : https://stackoverflow.com/questions/2426557/array-unique-for-objects

반응형