10

I know this is quite easily accomplished with a foreach, then a while->list, etc procedure, (I have already accomplished it), however I sense that my code is a bit dirty and it doesn't look like the best solution... I'm looking to use native PHP array functions to do the following:

I have two arrays that look like this:

[
    ['rank' => '579', 'id' => '1'],
    ['rank' => '251', 'id' => '2'],
]

and

[
    ['size' => 'S', 'status' => 'A', 'id' => '1'],
    ['size' => 'L', 'status' => 'A', 'id' => '2'],
]

And I need merge them to produce:

[
    ['size' => 'S', 'status' => 'A', 'id' => '1', 'rank' => '579'],
    ['size' => 'L', 'status' => 'A', 'id' => '2', 'rank' => '251'],
]

Is there a way to be able to merge two arrays with the id value (or any other) without going into a endless set of foreachs?

1
  • Are elements with the same id at the same index in both arrays? In other words, if the element with id 5 is at index 3 in the first array, will it also be at index 3 in the second array? Commented Nov 1, 2011 at 23:13

6 Answers 6

16

Use array_merge_recursive()

$array = array_merge_recursive($array1, $array2);

or make your own function (it may be faster)

function my_array_merge(&$array1, &$array2) {
    $result = Array();
    foreach($array1 as $key => &$value) {
        $result[$key] = array_merge($value, $array2[$key]);
    }
    return $result;
}
$array = my_array_merge($array1, array2);
print_r($array);
Sign up to request clarification or add additional context in comments.

2 Comments

Awesome!, thanks for this, FYI: the function approach works excellent as long as you need to discard those records that do not repeat on both arrays.
This doesn't technically answer the question. @OsvaldoM. wants to join based on the value of id, not by the keys.
7

As Ray noticed in a comment, the accepted answer does not actually answer the question. I was unable to find an answer, so I created the following small utility function:

function array_merge_callback($array1, $array2, $predicate) {
    $result = array();

    foreach ($array1 as $item1) {
        foreach ($array2 as $item2) {
            if ($predicate($item1, $item2)) {
                $result[] = array_merge($item1, $item2);
            }
        }
    }

    return $result;
}

Use it as follows:

array_merge_callback($array1, $array2, function ($item1, $item2) {
    return $item1['id'] == $item2['id'];
});

Comments

2

Have a nice one to merging arrays like another languages. It's because php have auto numbering array elements, and merging will dublicate or replace different elements by keys.

Now, it's changed.

// array_fork
  public static function array_fork() {
    $args = func_get_args();
    $result = array();
    foreach ($args as $arr) {
      is_array($arr) || exit('[' . __METHOD__ . '] Each item must be an array.');
      foreach ($arr as $key => $val) {
        if (is_array($val)) {
          // recursion
          !isset($result[$key]) && $result[$key] = array();
          $result[$key] = self::array_fork($result[$key], $arr[$key]);
          continue;
        }
        if (is_numeric($key)) {
          if (!in_array($arr[$key], $result))
            $result[] = $arr[$key];
        } else
          $result[$key] = $arr[$key];
      }
    }
    return $result;
  }

Comments

2
function custom_array_merge(&$array1, &$array2) {
    $result = Array();
    foreach ($array1 as $key_1 => &$value_1) {
        // if($value['name'])
        foreach ($array2 as $key_1 => $value_2) {
            if($value_1['name'] ==  $value_2['name']) {
                $result[] = array_merge($value_1,$value_2);
            }
        }

    }
    return $result;
}

// Pass $array1, &$array2 and change the $value_2['name'] // name based on which u want to merge.

1 Comment

This question doesn't have a name column.
2

It is not necessary to use a recursive technique nor multiple loops. Merge the two arrays together, then assign temporary first-level keys in the output array based on the rows' id value. If the id is being encountered for the first time, merge the row's data with an empty array; otherwise merge the pre-existing row data from result array. To remove the first-level keys after looping, call array_values().

Code: (Demo)

$a = [
    ['rank' => '579', 'id' => '1'],
    ['rank' => '251', 'id' => '2'],
];

$b = [
    ['size' => 'S', 'status' => 'A', 'id' => '1'],
    ['size' => 'L', 'status' => 'A', 'id' => '2'],
];

$result = [];
foreach (array_merge($a, $b) as $row) {
    $result[$row['id']] = $row + ($result[$row['id']] ?? []);
}
var_export(array_values($result));

Not represented by the question's sample data, if the two data sets have columnar data collisions in their respective id group, then later encountered values will overwrite earlier stored values. Demo To reverse that behavior, you can simply swap the data on either side of the "array union operator". Demo Be warned that array union is suitable in this case because the rows contain non-numeric keys. For other scenarios, it may be more reliable to use array_merge() or array_replace() instead of the union operator.

If the relating columns have different names, instead of grouping by $row['id'], cache the grouping value as a variable and fallback to the alternative column name. ($groupKey = $row['id'] ?? $row['otherId'];

Comments

1

ok, let's suppost your arrays are called $arr1 and $arr2, you could do this:

<?php
$newarray = Array();
foreach ($arr1 as $element=>$value){
    $newarray = array_merge($arr1[$element],$arr2[$element])
}
?>

1 Comment

This approach is ignoring the id values. It is simply merging on first level indexes (which is only correct by coincidence because the minimal reproducible example is not strong enough to expose this inappropriate logic).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.