81

I need to merge two arrays of objects into 1 array and remove duplicate email values.

How can I do that?

These are my sample arrays:

$array1 = [
    (object) ["email" => "gffggfg"],
    (object) ["email" => "wefwef@test.it"],
    (object) ["email" => "wefewf"],
];
$array2 = [
    (object) ["email" => "gffggfg@test.it"],
    (object) ["email" => "wefwef"],
    (object) ["email" => "wefewf"],
];

My expected result is:

[
   (object) ['email' => 'gffggfg'],
   (object) ['email' => 'wefwef@test.it'],
   (object) ['email' => 'wefewf'],
   (object) ['email' => 'gffggfg@test.it'],
   (object) ['email' => 'wefwef'],
]
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
itsme
  • 48,972
  • 96
  • 224
  • 345

8 Answers8

209

You can combine the array_merge() function with the array_unique() function (both titles are pretty self-explanatory)

$array = array_unique (array_merge ($array1, $array2));
dave
  • 2,762
  • 1
  • 16
  • 32
Jeroen
  • 13,056
  • 4
  • 42
  • 63
  • well as i can see array_merge() seems not calculating duplicates so array_unique() is deprecated in my case or not !? – itsme May 13 '12 at 14:44
  • 1
    `array_merge()` doesn't add duplicate keys, but when you have duplicate values with different keys, it does add those – Jeroen May 13 '12 at 14:47
  • 1
    Should add mention of SORT_REGULAR and other options to avoid errors with converting types. – Brandon Elliott Jul 31 '16 at 09:25
  • 5
    note: `array_unique` preserves keys, so for numerically indexed arrays if you need sequential keys, you can quickly rekey by wrapping with a call to `array_values` – highvolt Nov 30 '16 at 13:06
  • 2
    Despite the flood of upvotes and the green tick on this concise answer, [it is provably incorrect using the asker's sample data](https://3v4l.org/CoepY). – mickmackusa Jun 04 '22 at 06:52
13

If I understand the question correctly:

 $a1 = Array(1,2,3,4);
 $a2 = Array(4,5,6,7);
 $array =  array_diff(array_merge($a1,$a2),array_intersect($a1,$a2));
 print_r($array);

return

Array
(
[0] => 1
[1] => 2
[2] => 3
[5] => 5
[6] => 6
[7] => 7
)
Luca Rainone
  • 16,138
  • 2
  • 38
  • 52
  • sorry i forgot about i have multilevel array not simple array – itsme May 13 '12 at 14:49
  • Not only does this unexplained answer [not work with the asker's data](https://3v4l.org/UbCPn), even if it did, it would not be efficient because it is making value-based comparisions. In PHP, key-based comparisons always execute faster. – mickmackusa Jun 04 '22 at 06:50
5

I've been running some benchmarks of all the ways I can imagine of doing this. I ran tests on stacking lots of arrays of 10-20 string elements, resulting in one array with all unique strings in there. This sould be about the same for stacking just 2 arrays.

The fastest I've found was the simplest thing I tried.

$uniques = [];
foreach($manyArrays as $arr ) {
  $uniques = array_unique(array_merge($uniques, $arr));
}

I had branded this 'too naive to work', since it has to sort the uniques array every iteration. However this faster than any other method. Testing with 500.000 elements in manyArrays, each containing 10-20 strings om PHP 7.3.

A close second is this method, which is about 10% slower.

$uniques = [];
foreach($manyArrays as $arr ) {
  foreach($arr as $v) {
    if( !in_array($v, $uniques, false) ) {
      $uniques[] = $v;
    }
  }
}

The second method could be better in some cases, as this supports the 'strict' parameter of in_array() for strict type checking. Tho if set to true, the second option does become significantly slower than the first (around 40%). The first option does not support strict type checking.

Joeri Noort
  • 66
  • 1
  • 3
1

Faster solution:

function concatArrays($arrays){
    $buf = [];
    foreach($arrays as $arr){
        foreach($arr as $v){
            $buf[$v] = true;
        }
    }
    return array_keys($buf);
}


$array = concatArrays([$array1, $array2]);
kz_sergey
  • 677
  • 5
  • 19
1

Because the email properties in the array of objects contain non-numeric values, you can temporarily assign first level keys (with array_column()) then merge the two arrays with the union operator (a function-less action).

If the temporary keys are disruptive to your next process, you can re-index the array with array_values().

Code: (Demo)

var_export(
    array_values(
        array_column($array1, null, 'email')
        + array_column($array2, null, 'email')
    )
);

Output:

array (
  0 => 
  (object) array(
     'email' => 'gffggfg',
  ),
  1 => 
  (object) array(
     'email' => 'wefwef@test.it',
  ),
  2 => 
  (object) array(
     'email' => 'wefewf',
  ),
  3 => 
  (object) array(
     'email' => 'gffggfg@test.it',
  ),
  4 => 
  (object) array(
     'email' => 'wefwef',
  ),
)

"Merge and keep unique objects" will also work with a special flag.

Code: (Demo)

var_export(
    array_unique(
        array_merge($array1, $array2),
        SORT_REGULAR
    )
);
// same result as other snippet
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

Very old thread, but... OP's arrays contains objects. If I were op, I would declare a class that receives the sub arrays in the constructor with a __toString() function that returns the email. If op then makes his objects into instances of that class, array_unique should call __toString() when comparing

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 09 '22 at 11:42
0
<?php
   $array1 = array("yellow", "red", "green", "orange", "purple");
   $array2 = array("pink", "brown", "green", "orange", "red");
   $array = array_unique(array_merge($array1, $array2));
   print_r($array);
?>
 
Array
(
    [0] => yellow
    [1] => red
    [2] => green
    [3] => orange
    [4] => purple
    [5] => pink
    [6] => brown
)
Befkadu B
  • 1
  • 1
-1

A little bit late answer, but I just found that the array union operator + does the job quite greatly (found here at the 3rd section).

$array1 + $array2 = $array //if duplicate found, the value in $array1 will be considered ($array2 value for array_merge, if keys clearly specified)
Marek N
  • 15
  • 3
  • Not a good option to apply! You will get erroneous data if Array KEY is same even VALUE is different, eg: $array1 = Array( [0] => 0, [1] => 1, [2] => 2 ) $array2 = Array( [0] => 3 ) $array1 + $array2 = Array( [0] => 0, [1] => 1, [2] => 2 ) Better option will be array_unique (array_merge ($array1, $array2)) = Array( [0] => 0, [1] => 1, [2] => 2, [3] => 3 ) – Pran Sep 02 '20 at 17:06
  • This does not result in a Union of array's values, see [php.net](https://www.php.net/manual/en/language.operators.array.php#86379) – Aurovrata Dec 09 '20 at 11:21