0

I have an array comprised of PHP objects as such:

$objects[0] => $object->type => 'President'
               $object->name => 'Joe Blogs'
               $object->address => '123 Harry Street'

$objects[1] => $object->type => 'Secretary'
               $object->name => 'Joe Blogs'
               $object->address => '123 Harry Street'

$objects[2] => $object->type => 'Treasurer'
               $object->name => 'Jane Doe'
               $object->address => '456 Upton Street'

I would like to ignore the type parameter and end up with:

$objects[0] => $object->type => 'President'
               $object->name => 'Joe Blogs'
               $object->address => '123 Harry Street'

$objects[2] => $object->type => 'Treasurer'
               $object->name => 'Jane Doe'
               $object->address => '456 Upton Street'

I have tried a few different things, one of which was to unset the parameter type using a foreach loop and then trying to reset it, but I wasn't sure how to tie the two indexes together to reset them. Another was trying to use the union in the select command but that wasn't working 100% correctly either.

I am just not sure how to best manage the type parameter.

EDIT:

I have tried to make the query a little easier, it now returns a list of IDs that I will get the address information later. This is the new array that I would like to filter out any duplicates.

    $items['president'][0] = '1'
                       [1] = '2'
                       [2] = '3'

    $items['secretary'][0] = '1'
                       [1] = '4'
                       [2] = '5'

What I would like is

$items['president'][0] = '1'
                   [1] = '2'
                   [2] = '3'

$items['secretary'][1] = '4'
                   [2] = '5'

Is that any better? (Note: I can use both array structures, but the second one would be better)

8
  • 1
    I have tried a few difrent things Show your attempt(s) Commented Jun 28, 2015 at 5:14
  • I have tried to explain my attempts but nothing was even close to working so I wont show my attempt code Commented Jun 28, 2015 at 5:19
  • So where are we with this question ? Commented Jun 28, 2015 at 5:37
  • We are travelling well, I have edited the select function to make the array a little better. Is that easier? Commented Jun 28, 2015 at 6:19
  • 1
    Yes, it does thanks. when working with your answer I realised that possibly the second array will allow me to do things a little better. I am so sorry to stuff you around. Do you know a way for the second structure? Commented Jun 28, 2015 at 6:49

3 Answers 3

1

This should work for you:

Here I just go through each object from $objects. Then I go through all of your unique objects from $unique with array_reduce() and check if there is one object, which has the same values in name and address as the current one of the iteration.

If there in no object with the same values name and address in $unique I add it to it.

<?php

    $unique = [];

    foreach($objects as $o) {

        $duplicate = array_reduce($unique, function($keep, $v)use($o){
            if($v->name == $o->name && $v->address == $o->address)
                return $keep = TRUE;
        }, FALSE);

        if(!$duplicate)
            $unique[] = $o;

    }

    print_r($unique);

?>

output:

Array
(
    [0] => stdClass Object
        (
            [type] => President
            [name] => Joe Blogs
            [address] => 123 Harry Street
        )

    [1] => stdClass Object
        (
            [type] => Treasurer
            [name] => Jane Doe
            [address] => 456 Upton Street
        )

)

EDIT:

As from your updated question with the new array structure, something like this should work:

Just like before you have an array with the unique values and also an array to keep track on which values you already have in your $unique array. Then you can just loop through your array an check if the value isn't already in the values array.

<?php

    $unique = [];
    $values = [];

    foreach($items as $keyOne => $arr) {

        foreach($arr as $keyTwo =>$v) {
            if(!in_array($v, $values)) {
                $unique[$keyOne][$keyTwo] = $v;
                $values[] = $v;
            }
        }
    }   

    print_r($unique);


?>

output:

Array
(
    [president] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

    [secretary] => Array
        (
            [1] => 4
            [2] => 5
        )

)
Sign up to request clarification or add additional context in comments.

Comments

1

you can just use array_unique, this function compares objects using the toString method:

class obj{
    public $type;
    public $name;
    public $address;

    public function __construct($type, $name, $address){
        $this->type = $type;
        $this->name = $name;
        $this->$address = $address;
    }

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


$objects = array(
    new obj('President','Joe Bogs','123 Harry Street'),
    new obj('Treasurer','Joe Bogs','123 Harry Street'),
    new obj('Secretary','Jane Doh','456 Harry Street'),
);

// array_unique compares the toString value if given objects
$unique = array_unique($objects);

Or, if for some Reason you can not use __toString in your Object, write your own unique function that can compare using a custom function that returns a unique_id as you want it:

function custom_array_unique($array, $function){
    $res = array();
    foreach($array as $o){
        if(!isset($res[$function($o)])) {
            $res[$function($o)] = $o;
        }
    }
    return array_values($res);
}

$unique2 = custom_array_unique($objects, function($obj){
    return $obj->name . $obj->address;
});

var_dump($unique2);

6 Comments

But wont that see all three objects as unique as the $type is different?
No, i tried this, the idea is that array_unique compares each object to every other object in the array, if it is already there it will not produce it a second time in the result, however, as array_unique uses the __toString() function of an object ( if availabe ) to get a simpler String representation of the Object, and then compares the String representations instead of the objects itself, implementing that method in a way that fits your idea, ignoring the type will produce your expected result
However this may not be the most elegant solution, since you may want to use toString for something else, which is why i included the second example where you can define a function outside of the class that returns a special string that can then be compared.
Yes, that does make sense now, I don't have access to the __toString() function unfortunately.
@joschua011 I like the idea of your first code. But I think it's a bit of an overkill, to convert everything to the obj class, then take the unique values and then convert them back.
|
0

You can take the type as key, so it won't be duplicated, and in case you don't want to override, you can just verify it's existence by using array_key_exists, and after that you can array_values to get the order as required, see example below:

$newArray = array();
foreach($objects as $object){
    if(!array_key_exists($object->name, $newArray)){
        $newArray[$object->name] = $object;
    }
}
$newArray = array_values($newArray);
echo '<pre>';
print_r($newArray);

4 Comments

make sure to leave reason for downvote, so if there are any mistakes, it can be corrected!
Besides the syntax errors in your code it also doesn't output OP's expected output. I think you missed that part: I would like to ignore the 'type'
I think you also missed this part from my comment: Besides the syntax errors
Then please tell me what: $newArray(); should do? And also the output of your code still doesn't match the expected output from OP. (BTW: array_values($newArray); doesn't do what you think it does)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.