I have an array that looks like this:
我有一个这样的数组:
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"
]
]
In my case if the key "product_id" has the same value I want to reduce merge those arrays and add the total_price but I have to also save a new key to the new array: $quantity to store the number of array with the same key that existed before merging. So the final result should look like this:
在我的例子中,如果关键字“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"
]
]
Initially I tried with array_walk_recursive, but I got confused.
最初我尝试使用array_walk_recursive.com,但是我搞混了。
array_walk_recursive($products, function($value, $key) use (&$products_sold){
array_push($products_sold, isset($products_sold[$key]) ? $value + $products_sold[$key] : $value);
});
I know this is useless but I failed to realize how to do this. Any explanation would be helpful. Thank you all for your time!
我知道这是没有用的,但我没有意识到怎么做。任何解释都是有用的。谢谢大家!
2 个解决方案
#1
2
Try
试一试
$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;
}, []);
But I strongly recomment use BCMath functions instead of working with floats.
但我强烈建议使用BCMath函数,而不是使用浮点数。
So its better to write
所以最好写下来
$result[$index]['total_price'] = bcadd($result[$index]['total_price'], $product['total_price'], 2);
instead of
而不是
$result[$index]['total_price'] += $product['total_price'];
Update
更新
We can rewrite above version to nested foreach like so:
我们可以将上面的版本重写为嵌套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);
}
so we can see it is just foreach loop which calls function which contains another foreach. We need another foreach because we need the way to determine if array contains product_id. We can index result with product_id so we can avoid secind foreach:
我们可以看到它只是foreach循环它调用包含另一个foreach的函数。我们需要另一个foreach,因为我们需要确定数组是否包含product_id。我们可以用product_id索引结果因此我们可以避免secind 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;
}, []);
and then if you need indexes to be ordered from zero just call array_values($result)
如果需要从0开始排序索引只需调用array_values($result)
#2
2
Got it done! I should say I didnt use total_price
as string
so I can do addition.
做到了!我应该说,我没有使用total_price作为字符串,所以我可以添加。
$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]);
}
}
}
#1
2
Try
试一试
$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;
}, []);
But I strongly recomment use BCMath functions instead of working with floats.
但我强烈建议使用BCMath函数,而不是使用浮点数。
So its better to write
所以最好写下来
$result[$index]['total_price'] = bcadd($result[$index]['total_price'], $product['total_price'], 2);
instead of
而不是
$result[$index]['total_price'] += $product['total_price'];
Update
更新
We can rewrite above version to nested foreach like so:
我们可以将上面的版本重写为嵌套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);
}
so we can see it is just foreach loop which calls function which contains another foreach. We need another foreach because we need the way to determine if array contains product_id. We can index result with product_id so we can avoid secind foreach:
我们可以看到它只是foreach循环它调用包含另一个foreach的函数。我们需要另一个foreach,因为我们需要确定数组是否包含product_id。我们可以用product_id索引结果因此我们可以避免secind 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;
}, []);
and then if you need indexes to be ordered from zero just call array_values($result)
如果需要从0开始排序索引只需调用array_values($result)
#2
2
Got it done! I should say I didnt use total_price
as string
so I can do addition.
做到了!我应该说,我没有使用total_price作为字符串,所以我可以添加。
$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]);
}
}
}