ChenXiu Posted December 7, 2023 Share Posted December 7, 2023 I expected 4 items to arrive. Here are the SKU numbers: 1111 2222 2222 3333 When the box arrived and I opened it, I found these SKU numbers: 1111 2222 3333 3333 Upon opening the box, I immediately saw: • SKU 2222 was missing • there was an extra SKU 3333 My simple PHP script correctly shows the missing SKUs and the reconciled SKUs..... but why is it not showing the extra SKU? <?php $expected = array( '1111', '2222', '2222', '3333' ); $received = array( '1111', '2222', '3333', '3333' ); $expected = array_filter($expected); $received = array_filter($received); $expected_counts = array_count_values($expected); $received_counts = array_count_values($received); $not_received = array(); $reconciled = array(); $extra = array(); foreach ($expected_counts as $sku => $expected_count) { if (isset($received_counts[$sku])) { if ($received_counts[$sku] >= $expected_count) { $reconciled = array_merge($reconciled, array_fill(0, $expected_count, $sku)); } else { $reconciled = array_merge($reconciled, array_fill(0, $received_counts[$sku], $sku)); $not_received = array_merge($not_received, array_fill(0, $expected_count - $received_counts[$sku], $sku)); } } else { $not_received = array_merge($not_received, array_fill(0, $expected_count, $sku)); } } foreach ($received_counts as $sku => $received_count) { if (!isset($expected_counts[$sku])) { $extra = array_merge($extra, array_fill(0, $received_count, $sku)); } } // Output the results print_r($not_received); // SKUs that are missing print_r($reconciled); // SKUs that reconcile print_r($extra); // EXTRA (unexpected) SKUs ?> Quote Link to comment Share on other sites More sharing options...
Barand Posted December 7, 2023 Share Posted December 7, 2023 Try $expected = array( '1111', '2222', '2222', '3333' ); $received = array( '1111', '2222', '3333', '3333' ); $cExp = array_count_values($expected); $cRec = array_count_values($received); foreach (array_keys($cExp+$cRec) as $prod) { $e = $cExp[$prod] ?? 0; $r = $cRec[$prod] ?? 0; switch ($e <=>$r) { case -1: $check = 'Over'; break; case 0: $check = 'OK'; break; case 1: $check = 'Under'; break; } echo $prod . " Ordered: $e Received: $r - $check <br>"; } giving 1111 Ordered: 1 Received: 1 - OK 2222 Ordered: 2 Received: 1 - Under 3333 Ordered: 1 Received: 2 - Over 1 1 Quote Link to comment Share on other sites More sharing options...
kicken Posted December 7, 2023 Share Posted December 7, 2023 1 hour ago, ChenXiu said: but why is it not showing the extra SKU? Because you are only counting extras if they were not expected at all ($expected_counts[$sku] is not set). Your extra 3333 item was an expected sku, you just got too many. Your code can be much simpler by just calculating the counts of expected vs received for each sku rather than doing your array_fill stuff and checking index existence. $all_skus = array_merge(array_keys($expected_counts), array_keys($received_counts)); $reconciled = []; foreach ($all_skus as $sku){ $reconciled[$sku] = ($expected_counts[$sku] ?? 0) - ($received_counts[$sku] ?? 0); } $reconciled = array_filter($reconciled); First get a combined list of all possible SKUs, then loop over that list and for each SKU calculate # of expected (0 if unexpected) - # of received (0 if none received). Finally, filter out all the entries that ended up as 0 (received and expected match). You're left with an array of SKUs with either positive (missing) or negative (too many) items. If you really need an array of SKU's, you can expand the reconciled array out as necessary. Quote Link to comment Share on other sites More sharing options...
Solution Olumide Posted December 7, 2023 Solution Share Posted December 7, 2023 There is a slight error in the second foreach loop where you check for extra SKUs. You are comparing the received count with the expected count, but you should be checking if the received count is greater than the expected count. Try replacing the second foreach statement with this: foreach ($received_counts as $sku => $received_count) { if (!isset($expected_counts[$sku])) { $extra = array_merge($extra, array_fill(0, $received_count, $sku)); } elseif ($received_count > $expected_counts[$sku]) { $extra = array_merge($extra, array_fill(0, $received_count - $expected_counts[$sku], $sku)); } } 1 Quote Link to comment Share on other sites More sharing options...
ChenXiu Posted December 15, 2023 Author Share Posted December 15, 2023 (edited) Thank you all for your time. Edited December 15, 2023 by ChenXiu Deleted my grumpy outburst bourne of the frustration of not being as good at PHP as I would like to be. Quote Link to comment Share on other sites More sharing options...
ChenXiu Posted December 15, 2023 Author Share Posted December 15, 2023 (edited) On 12/7/2023 at 11:59 AM, Olumide said: foreach ($received_counts as $sku => $received_count) { if (!isset($expected_counts[$sku])) { $extra = array_merge($extra, array_fill(0, $received_count, $sku)); } elseif ($received_count > $expected_counts[$sku]) { $extra = array_merge($extra, array_fill(0, $received_count - $expected_counts[$sku], $sku)); } } I believe I mis-spoke. Olumide, your answer seems to work! Thank you for that!! You have restored my faith in PHP 😀 Edited December 15, 2023 by ChenXiu Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.