5

I have these 2 arrays.

First array is from user input $cart:

$cart = [
   ['id' => 3, 'weight' => 20, 'percentage' => 80],
   ['id' => 1, 'weight' => 50, 'percentage' => 80],
   ['id' => 2, 'weight' => 40, 'percentage' => 80],
];

and second array, I do a database SELECT id, stock WHERE id IN (3,1,2), resulting $db_item

$db_item = [
    ['id' => 1, 'stock' => 9539.00],
    ['id' => 2, 'stock' => 9468.00],
    ['id' => 3, 'stock' => 9295.00],
];

I want to add the stock attribute in second array to first array. Expected output:

$cart = [
   ['id' => 3, 'weight' => 20, 'percentage' => 80, 'stock' => 9295.00],
   ['id' => 1, 'weight' => 50, 'percentage' => 80, 'stock' => 9539.00],
   ['id' => 2, 'weight' => 40, 'percentage' => 80, 'stock' => 9468.00],
];

This is what I tried, and it works, but I don't think it is necessary to have foreach, array_filter, and array_column:

foreach ($cart as $key => $cart_item) {
    $item = array_filter($db_item, function($item) use ($cart_item) {
        return $item['id'] === $cart_item['id'];
    });
    $cart[$key]['stock'] = array_column($item, 'stock')[0];
}

anyone has better idea how to optimize this?


EDIT: following Mohammad's answer, I can use more attribute in second array

$keys = [];
foreach ($arr2 as $item) {
    $keys[$item['id']] = array(
        'attr1' => $item['attr1'],
        'attr2' => $item['attr2'],
        // and so on
    );
}

$newArr = array_map(function($item) use($keys){
    $item['attr1'] = $keys[$item['id']]['attr1'];
    $item['attr2'] = $keys[$item['id']]['attr2'];
    // and so on
    return $item;
}, $arr1);

EDIT2: found out that we can simplify the foreach loop with just a single line using array_column.

$keys = array_column($arr2, null, 'id');

$newArr = array_map(function($item) use($keys){
    $item['attr1'] = $keys[$item['id']]['attr1'];
    $item['attr2'] = $keys[$item['id']]['attr2'];
    // and so on
    return $item;
}, $arr1);
7
  • Why not get all the required data in a single query. If you show us the 2 queries, someone will tell you how to get all the info in one query Commented Nov 16, 2018 at 13:36
  • @RiggsFolly but first array is from user input, not from the query Commented Nov 16, 2018 at 13:36
  • Ah, good point :) Missed that :) :( Commented Nov 16, 2018 at 13:37
  • 2
    Funny thing, I have something of this nature in a cart system, but I just used two foreach... which is most likely the same performance as array_filter, since it rolls over the array just the same. We are talking mini-milli-seconds, so you probably are ok with what you have... unless you just want to make it more readable for anyone coming along your code in the future. Commented Nov 16, 2018 at 13:40
  • 1
    In programming, one of the best ways to optimize array lookups is the use of hash tables. PHP's associative arrays are an easy to use form of this. However, when dealing with only a few elements, I think any optimization is overoptimization. Commented Nov 16, 2018 at 13:47

2 Answers 2

2

Use combination of array_flip() and array_column() to create array contain id and index of second array.

Then use array_map() to add new key stock to first array.

$keys = array_flip(array_column($arr2, 'id'));
$newArr = array_map(function($item) use($keys, $arr2){ 
    $item['stock'] = $arr2[$keys[$item['id']]]['stock'];
    return $item;
}, $arr1);

Check result in demo

Also you can use foreach instead of array_flip()

$keys = [];
foreach ($arr2 as $item)
    $keys[$item['id']] = $item['stock'];

$newArr = array_map(function($item) use($keys){ 
    $item['stock'] = $keys[$item['id']];
    return $item;
}, $arr1);

Check result in demo

Sign up to request clarification or add additional context in comments.

1 Comment

this is the first time I see the use of array_flip. Nice idea btw, it is 2 lines shorter. But isn't doing array_flip + array_column + array_map is also doing 3 loops just like my solution above? I like your second solution, gonna change my code to use yours.
1

This can help too, one array_column + one array_map :

$arr2=array_column($arr2,'stock','id');
$arr1=array_map(function($val)use($arr2){$val['stock']=$arr2[$val['id']];return $val;},$arr1);

1 Comment

Oh nice, didn't know about array_column third parameter before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.