user1639319
user1639319

Reputation: 19

Joining rows from two 2d arrays where a common column value is found

I have two arrays that I would like to join into one. Both arrays have a common key=>value and I would like to insert the values of one array to the other so that I to create one array.

$array1 = [
    ['ID' => 123456, 'Key' => 1000, 'value' => 123.45],
    ['ID' => 789012, 'Key' => 1001, 'value' => 56748.17],
];

$array2 = [
    ['Key' => 1000, 'description' => 'desc1'],
    ['Key' => 1001, 'description' => 'desc2'],
];

I would like to join Array2 with Array1 so that the resulting Array is as follows:

array (
  0 => 
  array (
    'ID' => 123456,
    'Key' => 1000,
    'value' => 123.45,
    'description' => 'desc1',
  ),
  1 => 
  array (
    'ID' => 789012,
    'Key' => 1001,
    'value' => 56748.17,
    'description' => 'desc2',
  ),
)

So the arrays have been joined using the [Key] value as the, well, key. I've looked at array_merge and other function but I can't seem to get these two arrays to "merge" properly.

Upvotes: 1

Views: 1308

Answers (5)

mickmackusa
mickmackusa

Reputation: 47864

Use temporary first level keys to swiftly identify matching Key values between the two arrays. When an array2 row qualifies for merger with the first, use the union-assignment operator (+=). Call array_value() after looping if you don't want to preserve the temporary keys.

Code: (Demo)

$result = array_column($array1, null, 'Key');
foreach ($array2 as $row) {
    if (isset($result[$row['Key']])) {
        $result[$row['Key']] += $row;
    }
}
var_export(array_values($result));

Upvotes: 0

ernie
ernie

Reputation: 6356

@radashk's solution will work if you can always guarantee that $array1[$i] corresponds to $array2[$i]. From my reading of the question, that's not guaranteed, but instead you want to make sure that $array1[$i]['Key'] == $array2[$j]['Key'], and combine elements where those Keys match.

There may be a more elegant solution, but I would do it like this:

    // builds up new $tmpArray, using the Key as the index
$tmpArray = array();
foreach($array1 as $innerArray1){
            $tmpArray[$innerArray1['Key']] = $innerArray1;
}

    //Merges the values from $array2 into $tmpArray
foreach($array2 as $innerArray2) {
            if (isset($tmpArray[$innerArray2['Key']])) {
                $tmpArray[$innerArray2['Key']] = array_merge($tmpArray[$innerArray2['Key']], $innerArray2);
            }else{
                $tmpArray[$innerArray2['Key']] = $innerArray2;
            }

}

Upvotes: 0

J. Bruni
J. Bruni

Reputation: 20492

This is my approach:

$temp_ array = array_fill_keys (array_map(create_function('$a', 'return $a["Key"];'), $array_1) , $array_1);
$result = array();
foreach ($array_2 as $item) {
    if (isset($temp_array[$item['Key']])) {
        $result[] = array_merge($item, $temp_array[$item['Key']]);
    }
}

I have elaborated more in the code above, and reached this improved version:

function array_merge_items_by_common_key_value($key, $array_1, $array_2)
{
    $result = array();
    $temp_ array = array_fill_keys(array_map(create_function('$a', 'return $a["' . $key . '"];'), $array_1) , $array_1);
    foreach ($array_2 as $item)
    {
        $result[$item[$key]] = isset($temp_array[$item[$key]]) ? array_merge($item, $temp_array[$item[$key]]) : $item;
    }
    return array_values(array_merge($result, array_diff_key($array_1, $result)));
}

$merged_arrays = array_merge_items_by_common_key_value('Key', $temp_array, $array_2);

First, a temporary array is created: it is equal to $array_1, but its keys are the values to be matched.

Then, $array_2 is looped. When a match is found, the merge is done. If there is no match, then the $array_2 value is maintained, untouched.

Finally, those values in the $array_1 which were not matched, are also appended to the resulting array.

So, no item of both $array_1 or $array_2 is lost, while the matched items are merged.

Upvotes: 0

maaudet
maaudet

Reputation: 2358

You would have to do something like

$result = array();    

foreach ($a1 as $v1)
{
    foreach ($a2 as $k2 => $v2)
    {
        if ($v1['Key'] === $v2['Key'])
        {
            $result[] = array_merge($v1, $v2);
            unset($a2[$k2]);
            break;
        }
    }
}

Version with for loops

$result = array();

$c_a1 = count($a1);
$c_a2 = count($a2);

for ($i = 0; $i < $c_a1; $i++)
{
    for ($j = 0; $j < $c_a2; $j++)
    {
        if ($a1[$i]['Key'] === $a2[$j]['Key'])
        {
            $result[] = array_merge($a1[$i], $a2[$j]);
            unset($a2[$j]);
            $c_a2--;
            break;
        }
    }
}

Upvotes: 0

Kuro
Kuro

Reputation: 868

try this, its linear

$keyval = array();

foreach($array1 as $item)$keyval[$item['Key']] = $item['value'];
foreach($array2 as $key=>$item)$array2[$key]['description'] = isset($keyval[$item['Key']]) ? $keyval[$item['Key']] : '';

Upvotes: 0

Related Questions