4

After I merged two arrays like this array_merge($array1, $array2);, it becomes like this:

array(10) {
  [0]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "1"
    ["text"]=>
    string(5) "one"
  }
  [1]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "2"
    ["text"]=>
    string(8) "two"
  }
  [2]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "3"
    ["text"]=>
    string(4) "three"
  }
  [3]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "4"
    ["text"]=>
    string(8) "four"
  }
  [4]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "5"
    ["text"]=>
    string(3) "five"
  }
  [5]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "1"
    ["unit"]=>
    string(1) "0"
  }
  [6]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "2"
    ["unit"]=>
    int(0)
  }
  [7]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "3"
    ["unit"]=>
    int(0)
  }
  [8]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "4"
    ["unit"]=>
    string(1) "0"
  }
  [9]=>
  object(stdClass) (2) {
    ["id"]=>
    string(1) "5"
    ["unit"]=>
    int(1)
  }
}

Which means both arrays are literally merged. But what I wanted is since both arrays has common property called id and same value for it, it should become like:

array(2) {
  [0]=>
    object(stdClass) (2) {
      ["id"]=>
      string(1) "1"
      ["text"]=>
      string(5) "one"
      ["unit"]=>
      int(0)
    }
    [1]=>
    object(stdClass) (2) {
      ["id"]=>
      string(1) "2"
      ["text"]=>
      string(8) "two"
      ["unit"]=>
      int(2)
    }
  }

Note that array1 has id, text while array2 has id and unit.

I did refer here as tried the first answer which suggest to use array_map(), but for me I'm getting error saying argument 1 is not an array.

Combine two arrays into a single array based on a common column value

EDIT:

tried this (doesn't work):

$array1 = array_walk($array1, function(&$value) { $value = (array) $value; })
$array2 = array_walk($array2, function(&$value) { $value = (array) $value; })
function modifyArray($a, $b)
{
    if (!empty($a) && !empty($b)) {
        return array_merge($a, $b);
    } else if (!empty($a) && empty($b)) {
        return $a;
    }  else if (empty($a) && !empty($b)) {
        return $b;
    }
}

$new = array_map("modifyArray", $array1, $array2);
var_dump($new);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
112233
  • 2,406
  • 3
  • 38
  • 88
  • 3
    Because you have arrays of objects, you'll either need to walk through them doing this "manually", or convert them to arrays of arrays first – Mark Baker Feb 28 '17 at 08:16
  • @MarkBaker, can you show me how to do that, I've no idea how to convert them into array? – 112233 Feb 28 '17 at 08:18
  • 1
    `array_walk($myArray, function(&$value) { $value = (array) $value; });` – Mark Baker Feb 28 '17 at 08:22
  • `array_walk()` is "pass by reference; the returned value is boolean success/ failure, so don't assign that to your arrays, else you're overwriting the array – Mark Baker Feb 28 '17 at 10:02

1 Answers1

1

Merging objects is noticeably more tedious than arrays. I'd be tempted to convert the array of objects to an array or arrays in my own project, but I won't for this solution.

Unlike arrays which can enjoy array_merge() or the union operator, objects need to be pushed in manually.

I am temporarily grouping data by using the id values as first level keys in the loop, then optionally sorting by those keys, then re-indexing the output to remove the temporary keys.

Code: (Demo):

$output = [];
foreach ($poorly_merged as $object) {
    if (!isset($output[$object->id])) {
        $output[$object->id] = $object;
    } else {
        foreach ($object as $property => $value) {
            $output[$object->id]->{$property} = $value;
        }
    }
}
ksort($output); // optionally order by ids
var_export(array_values($output));

Or:

$output = [];
foreach ($poorly_merged as $object) {
    if (!isset($output[$object->id])) {
        $output[$object->id] = (object)[];
    }
    foreach ($object as $property => $value) {
        $output[$object->id]->{$property} = $value;
    }
}
ksort($output); // optionally order by ids
var_export(array_values($output));

Better practice would be not to merge your twp input arrays to form the $poorly_merged array. You could use iterate the second array of objects and add that data into the first -- this would be a more direct solution.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136