2

I have two arrays $a and $b

$a = [
    '0' => [
        'name'=>'Apple',
        'id' => 1
    ],
    '1' => [
        'name'=>'Banana',
        'id' => 2
    ],
    '2' => [
        'name' => 'orange',
        'id' => 3
    ]
];

AND

$b = [
    '0' => [
        'price'=> 20,
        'a_id' => 2
    ],
    '1' => [
        'price'=> 10,
        'a_id' => 3
    ],
    '3' => [
        'price'=> 30,
        'a_id' => 1
    ]
];

I am trying to create another array with mapping with id(array $a), a_id (array $b), where my output will looks like:

$a = [
    '0' => [
        'id' => 1
        'name'=>'Apple',
        'price' => 30
    ],
    '1' => [
        'id' => 2
        'name'=>'Banana',
        'price' => 20
    ],
    '2' => [
         'id' => 3
         'name' => 'orange',
         'price' => 10
    ]
];

I have tried by array map

$combined = array_map(null,$a,$b);

But this result is not my desire result. How can I map my 1st array with 2nd array related by $a['id'] = $b['a_id']?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136

5 Answers5

2

This should work, also if there's no price for an item in the array $b then the default price 0 will be added.

<?php

$result = [];

$t = array_column($b, 'a_id');

foreach($a as $k => $v) {
    
    $index = array_search($v['id'], $t);
    $v['price'] = $index !== FALSE ? $b[$index]['price'] : 0;
    $result[] = $v;

}

print_r($result);

?>

Result:

(
    [0] => Array
        (
            [name] => Apple
            [id] => 1
            [price] => 30
        )

    [1] => Array
        (
            [name] => Banana
            [id] => 2
            [price] => 20
        )

    [2] => Array
        (
            [name] => orange
            [id] => 3
            [price] => 10
        )
)
OMi Shah
  • 5,768
  • 3
  • 25
  • 34
1

You can do it as follows:

foreach($a as $k => $item)
{        
    $price = 0;    

    foreach($b as $priceItem)
    {
       if($priceItem['a_id'] === $item['id'])
       {
            $price = $priceItem['price'];
            break;
       }   
    }

    $a[$k]['price'] = $price;
}

However, this isn't too efficient as every new price and item will exponentially increase the loops required.

If you are able to use the product IDs as the key in your first array, you could do it a lot more efficiently:

// Key $a by product ID
$a = [
    1 => [
        'name'=>'Apple',
        'id' => 1
    ],
    2 => [
        'name'=>'Banana',
        'id' => 2
    ],
    3 => [
        'name' => 'orange',
        'id' => 3
    ]
];

foreach($b as $priceItem)
{   
    $a[$priceItem['a_id']]['price'] = $priceItem['price'];
}
jd182
  • 3,180
  • 6
  • 21
  • 30
1

You can use this code

$result = [];

for($i=0; $i<sizeof($a); $i++){
    if(array_key_exists($i,$b)){
        $b[$i]['id']=$b[$i]['a_id'];
        unset($b[$i]['a_id']);
    }
    $result[] = array_merge($a[$i], array_key_exists($i,$b)?$b[$i]:array());
}

print_r($result);
Bellash
  • 7,560
  • 6
  • 53
  • 86
  • If I increase array $a element, this solution making error.My array $a element can be increase and it can be grater then array $b. – Rezaul Zablu Jul 29 '21 at 17:10
1

Not that this is more efficient, but maybe a bit more flexible, and readable. Its on you!

<?php

$a = [
    '0' => ['name'=>'Apple', 'id' => 1],
    '1' => ['name'=>'Banana', 'id' => 2],
    '2' => ['name' => 'orange', 'id' => 3],
    '3' => ['name' => 'extra', 'id' => 4]
];
$b = [
    '0' => ['price'=> 20, 'a_id' => 2],
    '1' => ['price'=> 10, 'a_id' => 3],
    '3' => ['price'=> 30, 'a_id' => 1]
];

$lookup = [];
foreach($b as $k => $v) {
    if (array_key_exists($v['a_id'], $lookup)) {
        // you have multiple prices... do something, throw an error, log an error, overwrite the value
        // what ever you want
    } else {
        // in case you have multiple array items you want to copy over
        // you can later merge the array
        // if its only ever going to be prices , you can just take the price instead of the unset
        $parent_id = $v['a_id'];
        unset($v['a_id']);
        $lookup[$parent_id] = $v;
    }
}

// in case you have more values that you want push, if nothing exists
$default_values = ['price' => 0];

foreach($a as $k => &$v) {

    if (array_key_exists($v['id'], $lookup)) {
        $v = array_merge($v, $lookup[$v['id']]);
    } else {
        $v = array_merge($v, $default_values);
    }

} 
/* bit less readable
foreach($a as $k => &$v)
    $v = array_merge($v, array_key_exists($v['id'], $lookup) ? $lookup[$v['id']] : $default_values);
*/
print_r($a);

result

Array
(
    [0] => Array (
        [name] => Apple [id] => 1 [price] => 30
    )
    [1] => Array (
        [name] => Banana [id] => 2 [price] => 20
    )
    [2] => Array (
        [name] => orange [id] => 3 [price] => 10
    )
    [3] => Array (
        [name] => extra [id] => 4 [price] => 0
    )
)
Gauthier
  • 1,251
  • 10
  • 25
0

Be careful to avoid nested array_search() calls, this will not be the most efficient approach. This task should be completed with a On on each array; in other words, do not iterate either of the arrays more than once if you want the best possible time complexity.

  1. Use array_column() with a null 2nd parameter to temporarily assign id values as first level keys -- this will make relating the two arrays very easy and efficient.
  2. My snippet below will use "array destructuring" to unpack the $b data and push price elements into the result set.
  3. When the loop is finished, use array_values() to re-index the output array (if you wish).

Code: (Demo)

$result = array_column($a, null, 'id');
foreach ($b  as ['a_id' => $a_id, 'price' => $result[$a_id]['price']]);
var_export(array_values($result));

It's just that easy/simple.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136