객체에 대한 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
경고 : 엄격한 비교 ( "===")가 아닌 "=="비교를 사용합니다.
따라서 객체 배열 내에서 중복을 제거하려면 객체 ID (인스턴스)를 비교하는 것이 아니라 각 객체 속성을 비교해야합니다.
==( 차이를 보여 주어야 함 ===) 때문에 값 ( ) 또는 정체성 ( ) 에 대한 비교의 차이를 보여주지 않습니다 . 예제는 codepad.viper-7.com/8NxWhG 를 참조하십시오 . $bam->prop = 'test2';'test1'
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
)
)
배열에서 중복 된 인스턴스 (예 : "==="비교)를 필터링해야하는 경우 정확하고 빠른 방법입니다.
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
array_unique는 요소를 문자열로 캐스팅하고 비교를 수행하여 작동합니다. 객체가 문자열로 고유하게 캐스팅되지 않는 한 array_unique와 함께 작동하지 않습니다.
대신 개체에 대한 상태 저장 비교 함수를 구현하고 array_filter 를 사용 하여 함수가 이미 본 것을 버리십시오.
array_uniqueSORT_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 필터 콜백 함수에 대한 참조로 배열을 전달해야합니다. 그렇지 않으면 작동하지 않습니다.