0

I'm trying to create an array that groups together similar/identical items and creates a count/ tally of the number of times that item occurs.

I've managed to get an array to output that looks something like this:

Code            Item
WX4RCDWK3VJ7M   Caesar Salad
WX4RCDWK3VJ7M   Caesar Salad
YTZ8346445MFT   Wolfblass Cab Sauvignon
XGZ4NDEDKTCGY   Rib Eye 16 oz
A50NPRW74C5K6   Filet 8 oz
A50NPRW74C5K6   Filet 8 oz
A50NPRW74C5K6   Filet 8 oz

I'd like the output to look something like this:

Code            Item                      Count
WX4RCDWK3VJ7M   Caesar Salad              2
YTZ8346445MFT   Wolfblass Cab Sauvignon   1 
XGZ4NDEDKTCGY   Rib Eye 16 oz             1
A50NPRW74C5K6   Filet 8 oz                3

Currently I've managed to get to this point correctly, based on an original extensive multidimensional array ( $orders[]['lineItems']['elements'][]):

foreach ($orders as $order){
  foreach ($order['lineItems']['elements'] as $item){
       $product['code'] = $item['item']['code'];
       $product['name'] = $item['name'];
       $products[] = $product;
  }
}
print_r ($products);

I've tried using array_count_values, but get an error in my terminal saying "Can only count STRING and INTEGER values!".

I've tried looping the product['code'] in as a key for my output array ($products) and increment a product['count'] item.

This seems like it should be very basic, but I'm missing something.

EDIT: The original array that I'm looping through looks something like this (I have taken out most irrelevant pieces) - this is a single "order", there are many of these.

"orders" : {
    "elements": [1]
        0: {
            "currency" : "EUR"
            "lineItems": {
                "elements": [2]
                    0:  {
                        "item": {
                                "code": "ASDFXCVDGRRGTG"
                            }-
                        "name": "Caesar Salad"
                        "price": 400
                    },
                    1:  {
                        "item": {
                                "code": "QWEWERRTERTT"
                            }-
                        "name": "Crafty Beer"
                        "price": 100
                    }
            }
            "createdTime": 1453386417000      
    }
}

EDIT2 - changed 'id' to 'code' to avoid confusion between numeric and non-numeric arrays

4
  • 1
    This comes from a DB? Do it in the query. Commented Jan 21, 2016 at 16:05
  • No it doesn't, comes from a REST Api Commented Jan 21, 2016 at 16:40
  • 1
    What does original array look like? Commented Jan 21, 2016 at 16:46
  • There you go - it's quite a sizeable array, but I've tried to filter it down to the relevant pieces - apologies for any minor formatting errors Commented Jan 21, 2016 at 17:51

2 Answers 2

1

The outer part of your loop looks like it should work for this. You just need to make a couple of changes to how it is building the grouped array.

foreach ($orders as $order) {
    foreach ($order['lineItems']['elements'] as $item) {
        // use the item id as a key in the array you are building
        $id = $item['item']['id'];

        if (isset($products[$id])) {
            // if the item has already been added, increment the count
            $products[$id]['Count']++;
        } else {
            // otherwise, add the item with an initial count of 1
            $products[$id]['ID'] = $id;
            $products[$id]['Item'] = $item['name'];
            $products[$id]['Count'] = 1;
        }
    }
}

The resulting $products array will have item IDs as keys. If you want it to have numeric keys instead, you can then do:

$products = array_values($products);
Sign up to request clarification or add additional context in comments.

2 Comments

How would you adjust this so that the final array has a numerical index?
Did you see the part at the end of the answer about using array_values? Did that not work?
1

You want counts by id. Use a separate array, keyed by id to do this.

$itemCounts = array();
foreach($products as $product)
{
    if (!isset($itemCounts[$product['code']]))
    {
        $itemCounts[$product['code']] = 0;
    }
    $itemCounts[$product['code']]++;
}
print_r($itemCounts);

If you want, you can get everything in a single array, still keyed by ID:

$itemCounts = array();
foreach($products as $product)
{
    if (!isset($itemCounts[$product['code']]))
    {
        $itemCounts[$product['code']] = array(
            'name' => $product['name'],
            'count' => 0
        );
    }
    $itemCounts[$product['code']]['count']++;
}
print_r($itemCounts);

You can optimize this by not creating $products at all. Replace $products in my code above with the corresponding item from the original $orders array.

EDIT

The code snippets above give you the correct array structure to handle this type of data. To produce your exact desired output from the second code snippet above, you'd want to do something like this:

foreach($itemCounts as $code => $item)
{
    print $code . " " . $item['name'] . " " . $item['count'] . "\n";
}

4 Comments

Thanks for the attempt, I'm trying some variations, but this doesn't seem to group items in the output array i.e. collapse items of same name/ code into a single row and count. I changes the question slightly to emphasise that my output is actually a numeric array, it may have been confusing with the 'id' field
Not sure what you mean. It does exactly what you asked. I added an edit to show you how to print it. Also, I'm assuming that you'll first run your own code to generate the $products array, since your original question did not include a description of the $orders array.
Also, in my original answer i misnamed your 'code' key as 'id'. It has been fixed in my answer above.
You're right it is spitting out the correct array, thank you. I'm trying to return it from a function and it didn't show up for some other to be addressed issue!

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.