【问题标题】:Group identical items in PHP array & count在 PHP 数组中分组相同的项目并计数
【发布时间】:2016-01-21 16:01:28
【问题描述】:

我正在尝试创建一个数组,将相似/相同的项目组合在一起,并创建该项目出现次数的计数/计数。

我已经设法得到一个输出数组,看起来像这样:

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

我希望输出看起来像这样:

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

目前我已经成功地基于一个原始的扩展多维数组 ($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);

我尝试使用 array_count_values,但在我的终端中出现错误提示“只能计算 STRING 和 INTEGER 值!”。

我尝试将 product['code'] 循环作为我的输出数组 ($products) 的键并增加 product['count'] 项。

这似乎应该是非常基本的,但我错过了一些东西。

编辑:我循环的原始数组看起来像这样(我已经取出了最不相关的部分) - 这是一个单一的“订单”,其中有很多。

"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 - 将 'id' 更改为 'code' 以避免数字和非数字数组之间的混淆

【问题讨论】:

  • 这来自数据库?在查询中执行。
  • 不,不是,来自 REST Api
  • 原始数组长什么样子?
  • 你去 - 这是一个相当大的数组,但我已经尝试将它过滤到相关的部分 - 对任何小的格式错误表示歉意

标签: php arrays loops foreach


【解决方案1】:

你的循环的外部看起来应该适用于此。您只需要对其构建分组数组的方式进行一些更改。

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;
        }
    }
}

生成的 $products 数组将以项目 ID 作为键。如果你希望它有数字键,你可以这样做:

$products = array_values($products);

【讨论】:

  • 这也很完美 - 并且稍微干净一些。谢谢
  • 你将如何调整它以使最终数组具有数字索引?
  • 你看到答案末尾关于使用array_values的部分了吗?这没有用吗?
【解决方案2】:

您希望按 id 计数。使用一个单独的数组,以 id 为键来执行此操作。

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

如果您愿意,您可以将所有内容放在一个数组中,仍以 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);

您可以通过根本不创建 $products 来优化它。将我上面代码中的 $products 替换为原始 $orders 数组中的相应项目。

编辑

上面的代码 sn-ps 为您提供了正确的数组结构来处理这种类型的数据。要从上面的第二个代码 sn-p 生成您想要的确切输出,您需要执行以下操作:

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

【讨论】:

  • 感谢您的尝试,我正在尝试一些变体,但这似乎并没有将输出数组中的项目分组,即将相同名称/代码的项目折叠成一行并计数。我稍微改变了问题以强调我的输出实际上是一个数字数组,它可能与“id”字段混淆
  • 不确定你的意思。它完全按照您的要求进行。我添加了一个编辑来向您展示如何打印它。另外,我假设您将首先运行自己的代码来生成 $products 数组,因为您最初的问题没有包含对 $orders 数组的描述。
  • 另外,在我的原始答案中,我将您的“代码”键错误地命名为“id”。它已在我上面的答案中得到修复。
  • 你说得对,它吐出了正确的数组,谢谢。我正在尝试从函数中返回它,但它没有显示为其他需要解决的问题!
猜你喜欢
  • 1970-01-01
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多