1

I have an Object Array with few fields.

I was able to get the Array unique for this Object Array using below code:

$aa = array_unique($dd,SORT_REGULAR);

But what i am trying to achieve is, i want to exclude certain keys in object from "unique check". Lets say all object values are matching except "valid_from" and "valid_to" date fields.

Below is array structure:

Array
(
    [9948] => stdClass Object
        (
            [payrate] => 78.00000
            [valid_from] => 03/01/2017
            [valid_to] => 03/31/2017
        )

    [15133] => stdClass Object
        (
            [payrate] => 78.00000
            [valid_from] => 04/01/2017
            [valid_to] => 04/31/2017
        )

)

So as per above case as my pay rate is same in both object, but as valid from and valid to are different it will be still considered different entries.

Is there anyway we can specify exclude certain fields out for Array Unique for Array of Objects.

Wolverine
  • 455
  • 3
  • 8
  • 26

2 Answers2

0

You can use array_filter with a custom callback to filter out some elements from an array.

All you have to do is to implement your filter logic. Here a simple example:

<?php
$array = json_decode(
    '[{"name":"foo","count":2},{"name":"foo","count":10},{"name":"baz","count":5},{"name":"foobar","count":10}]'
);

$uniqueCheck = [];

$filtered = array_filter(
    $array,
    function ($element) use (&$uniqueCheck) {
        if (isset($uniqueCheck[$element->name])) {
            return false;
        }

        $uniqueCheck[$element->name] = true;

        return true;
    }
);

print_r($array);
print_r($filtered);

This will produce:

Array
(
    [0] => stdClass Object
        (
            [name] => foo
            [count] => 2
        )

    [1] => stdClass Object
        (
            [name] => foo
            [count] => 10
        )

    [2] => stdClass Object
        (
            [name] => baz
            [count] => 5
        )

    [3] => stdClass Object
        (
            [name] => foobar
            [count] => 10
        )

)

Array
(
    [0] => stdClass Object
        (
            [name] => foo
            [count] => 2
        )

    [2] => stdClass Object
        (
            [name] => baz
            [count] => 5
        )

    [3] => stdClass Object
        (
            [name] => foobar
            [count] => 10
        )

)

Edit: Changed $element->count based check to "unique $element->name check".

Kyoya
  • 343
  • 2
  • 5
0

See also array_unique for objects?

In case you work with non-stdClass object you could implement __toString to use array_unique to filter.

To filter on unique stdClass, using only a few of the attributes you could try something like:

From PHP 7 onwards you could use array_column to get a value from a stdClass, so if you use PHP7:

array_unique(array_column($array,'payrate'));

Before PHP 7 you could try:

array_unique(array_map(function($item) {return $item->payrate;},$array);

In case there are more attributes to compare there are different ways. array_reduce is just one of them.

The outcome of this one will not have any duplicates. So if all attributes match, the item will be filtered.

$attributes = ['payrate','date']
$filtered = array_reduce($array,function($carry,$item) use ($attributes) {
    if(count(array_filter($attributes,function ($attribute) use ($carry, $item) {
            return !in_array($item->$attribute,array_map(function($carriedItem) use ($attribute) {
                return $carriedItem->$attribute;
            },$carry));
        }))) {
        $carry[] = $item;
    }
    return $carry;
},[]);

see http://sandbox.onlinephpfunctions.com/code/5f8171d76362ada7e165afeaadbecffc6cdd497a

Community
  • 1
  • 1
Maarten van Middelaar
  • 1,691
  • 10
  • 15