PHP-循环遍历多维数组,如果找到密钥则减少数组

时间:2017-05-23 11:06:54

标签: php arrays multidimensional-array

我有一个如下所示的数组:

array:3 [
  0 => array:5 [
    "id" => 18
    "product_id" => 37
    "total_price" => "643.00"
    "created_at" => "2017-05-02 13:22:35"
    "updated_at" => "2017-05-02 13:22:35"
  ]
  1 => array:5 [
    "id" => 19
    "product_id" => 36
    "total_price" => "532.00"
    "created_at" => "2017-05-02 13:23:47"
    "updated_at" => "2017-05-02 13:23:47"
  ]
  2 => array:5 [
    "id" => 20
    "product_id" => 36
    "total_price" => "532.00"
    "created_at" => "2017-05-03 13:20:47"
    "updated_at" => "2017-05-03 13:20:47"
  ]
]

在我的情况下,如果键“product_id”具有相同的值,我想减少合并这些数组并添加total_price但我还必须将新键保存到新数组:$ quantity来存储数组的数量合并之前存在的相同密钥。 所以最终的结果应该是这样的:

array:2 [
  0 => array:5 [
    "id" => 18
    "product_id" => 37
    "total_price" => "643.00"
    "quantity"   => 1
    "created_at" => "2017-05-02 13:22:35"
    "updated_at" => "2017-05-02 13:22:35"
  ]
  1 => array:5 [
    "id" => 19
    "product_id" => 36
    "total_price" => "1064.00"
    "quantity"   => 2
    "created_at" => "2017-05-02 13:23:47"
    "updated_at" => "2017-05-02 13:23:47"
  ]
]

最初我尝试使用array_walk_recursive,但我感到困惑。

array_walk_recursive($products, function($value, $key) use (&$products_sold){
            array_push($products_sold, isset($products_sold[$key]) ?  $value + $products_sold[$key] : $value);
        });

我知道这没用,但我没有意识到如何做到这一点。任何解释都会有所帮助。 谢谢大家的时间!

2 个答案:

答案 0 :(得分:2)

尝试

$result = array_reduce($products, function ($result, $product) {
    foreach ($result as $index => $value) {
        if ($value['product_id'] == $product['product_id']) {
            $result[$index]['total_price'] += $product['total_price'];

            return $result;
        }
    }
    $result[] = $product;
    return $result;
}, []);

但我强烈建议使用BCMath函数而不是使用浮点数。

所以写得更好

$result[$index]['total_price'] = bcadd($result[$index]['total_price'], $product['total_price'], 2);

而不是

$result[$index]['total_price'] += $product['total_price'];

<强>更新

我们可以将上述版本重写为嵌套的foreach,如下所示:

$reducer = function ($result, $product) {
    foreach ($result as $index => $value) {
        if ($value['product_id'] == $product['product_id']) {
            $result[$index]['total_price'] += $product['total_price'];

            return $result;
        }
    }
    $result[] = $product;
    return $result;
};

$result = [];

foreach($products as $product) {
    $result = $reducer($result, $product);
}

所以我们可以看到它只是foreach循环,它调用包含另一个foreach的函数。 我们需要另一个foreach因为我们需要确定数组是否包含product_id的方法。 我们可以使用product_id索引结果,因此我们可以避免使用foreach:

$result = array_reduce($products, function ($result, $product) {
    $productId = $product['product_id'];
    if(isset($result[$productId])) {
        $result[$productId]['total_price'] += $product['total_price'];
        return $result;
    }
    $result[$productId] = $product;
    return $result;
}, []);

然后如果您需要从零开始订购索引,请致电array_values($result)

答案 1 :(得分:2)

完成了!我应该说我没有使用total_price作为string所以我可以做补充。

$stuff = array(
    array(
        "id" => 18,
        "product_id" => 37,
        "total_price" => 643.00,
        "created_at" => "2017-05-02 13:22:35",
        "updated_at" => "2017-05-02 13:22:35"),

    array(
        "id" => 19,
        "product_id" => 36,
        "total_price" => 532.00,
        "created_at" => "2017-05-02 13:23:47",
        "updated_at" => "2017-05-02 13:23:47"),

    array(
        "id" => 20,
        "product_id" => 36,
        "total_price" => 532.00,
        "created_at" => "2017-05-03 13:20:47",
        "updated_at" => "2017-05-03 13:20:47")
    );

for ($i=0; $i < count($stuff); $i++) { 
    $product_id = $stuff[$i]["product_id"];
    foreach ($stuff as $key => $value) {
        if($value["product_id"] === $product_id && $i !== $key) {
            $stuff[$i]["total_price"] += $value["total_price"];
            unset($stuff[$key]);
        }
    }
}