Пересобрать массив PHP

722
07 февраля 2017, 22:58

Всем привет! Есть массив foreach($products as $ val) {}:

Array(
[0] => Array
    (
        [product_id] => 31
        [quantity] => 5
        [price] => $100.00
        [total] => $500.00
    )
[1] => Array
    (
        [product_id] => 47
        [quantity] => 2
        [price] => $200.00
        [total] => $400.00
    )
[2] => Array
    (
        [product_id] => 47
        [quantity] => 2
        [price] => $200.00
        [total] => $400.00
    )
[3] => Array
    (
        [product_id] => 47
        [quantity] => 2
        [price] => $200.00
        [total] => $400.00
    )
[4] => Array
    (
        [product_id] => 50
        [quantity] => 1
        [price] => $300.00
        [total] => $300.00
    )
[5] => Array
    (
        [product_id] => 50
        [quantity] => 1
        [price] => $300.00
        [total] => $300.00
    )
[6] => Array
    (
        [product_id] => 50
        [quantity] => 1
        [price] => $300.00
        [total] => $300.00
    )

)

Как посчитать сумму quantuty, если совпадает product_id, после unset удалить дубли по product_id

Результат должен иметь вид:

Array(
[0] => Array
(
    [product_id] => 31
    [quantity] => 5
    [price] => $100.00
    [total] => $500.00
)
[1] => Array
(
    [product_id] => 47
    [quantity] => 6
    [price] => $200.00
    [total] => $1200.00
)
[2] => Array
(
    [product_id] => 50
    [quantity] => 3
    [price] => $300.00
    [total] => $900.00
)
Answer 1
$new_arr=array(); 
foreach ($products as $key => $value) {
        $product_id=$value['product_id'];
        $quantity=$value['quantity'];
        $price=$value['price'];
        if (array_key_exists($product_id, $new_arr)) {
            $new_quantity=$new_arr[$product_id]['quantity']+$quantity;
            $new_arr[$product_id]['quantity']=$new_quantity;
            $new_arr[$product_id]['total']=$new_quantity*$price;
        } else {
            $new_arr[$product_id]['quantity']=$quantity;
            $new_arr[$product_id]['price']=$price;
            $new_arr[$product_id]['total']=$quantity*$price;
        }
}

Изначально следовало бы ключами массива делать не номер по порядку, а уникальный ИД товара. Ушло бы много мороки. А валюту следует хранить отдельно ($200*2 не посчитает).

Дополнил на основе комментариев

    $products=Array(
        '0' => Array
            (
                'product_id' => '47',
                'quantity' => '5',
                'price' => '200.00',
                'total' => '1000.00',
                'thumb' => 'thumb.00',
                'name' => 'name.00',
                'model' => 'model.00',
                'size' => '34'
            ),
        '1' => Array
            (
                'product_id' => '47',
                'quantity' => '2',
                'price' => '200.00',
                'total' => '400.00',
                'thumb' => 'thumb.00',
                'name' => 'name.00',
                'model' => 'model.00',
                'size' => '56'
            )
        );
    $new_arr=array();
    $balast_values_names=array(1 => 'thumb', 2 => 'name', 3 => 'model'); // тут все статичные переменные
foreach ($products as $key => $value) {
    $product_id=$value['product_id'];
    $quantity=$value['quantity'];
    $price=$value['price'];
    /*
        Играем на свойстве ключей массивов - может быть только один уникальный ключ. И в качестве ключа берём product_id.
        Перебираем циклом (немного выше мы уже начали перебор) все значения исходного массива. И формируем новый.
        Ключами нового массива будет product_id исходного. Таким образом, если встретим в исходном массиве два товара с одним product_id,
        то более новый перезапишет более старый в новом массиве. А нам нужно сохранить все данные. Особеннно количество товаров.
        Потому array_key_exists($product_id, $new_arr) проверяет, есть ли у нас в новом массиве уже значение ключа равное product_id из исходого массива
        Если есть, до дополняем в новом массиве его дополнительными данными из старого (добавляем количество заказов, пересчитываем стоимость и т.п.)
        Если нет, то просто добавляем все данные
    */
    if (array_key_exists($product_id, $new_arr)) {
        $new_quantity=$new_arr[$product_id]['quantity']+$quantity;
        $new_arr[$product_id]['quantity']=$new_quantity;
        $new_arr[$product_id]['total']=$new_quantity*$price;
        //это код для размеров обуви (если от размера не зависит цена)
        $want_to_add_in_array_size=$value['size'];
        //тут смотрим, если размер обуви, который хотим добавить не совпадает с теми, что уже есть в новом массиве, то добавляем его. А если совпадает, то ничего не делаем
        if (!in_array($want_to_add_in_array_size, $new_arr[$product_id]['size'])) { 
            $new_arr[$product_id]['size'][]=$want_to_add_in_array_size;
        }
    } else {
        $new_arr[$product_id]['quantity']=$quantity;
        $new_arr[$product_id]['price']=$price;
        $new_arr[$product_id]['total']=$quantity*$price;
        //если каждый ИД товара - уникальная единица, то (размеры предусмотрены ниже)
        //переносим все значения статичным переменных
        foreach ($balast_values_names as $key2 => $balast) {
            $new_arr[$product_id][$balast]=$value[$balast];
        }
        //размеры загоняем сюда (если от размера не зависит стоимость, конечно)
        $new_arr[$product_id]['size'][]=$value['size'];
    }
}
    print_r($products);
    echo '<br><br><br>';
    print_r($new_arr);

В результате получим

Array
(
    [47] => Array
        (
            [quantity] => 7
            [price] => 200.00
            [total] => 1400
            [thumb] => thumb.00
            [name] => name.00
            [model] => model.00
            [size] => Array
                (
                    [0] => 34
                    [1] => 56
                )
        )
)
Answer 2

Если вам нужен уникальный результат, может так?

<?php
$uniqid = array();
$uniqArray = array();
$count = 0;
foreach($products as $val) {
if(!in_array($val['product_id'],$uniqid)){
array_push($uniqArray,$val);
$count++;
}
}
print_r($uniqArray);
print_r($count);
?>
Answer 3

Как-то так:

function getArray($products) {
    $products_new = [];
    foreach($products as $key => $val) {
        if(!isset($products_new[$val['product_id']])) {
            $products_new[$val['product_id']]["quantity"] = $val['quantity'];
            $products_new[$val['product_id']]["price"] = $val['price'];
        } else {
            $products_new[$val['product_id']]["quantity"] += $val['quantity'];
        }
        $products_new[$val['product_id']]["total"] = $val['total'] * $products_new[$val['product_id']]["quantity"];
    }
    return $products_new;
}
print_r(getArray($products));

Ну и привидения к старому виду (если это нужно):

function getOldArray($products_new){
    $products = [];
    foreach($products_new as $key => $val) {
        $products[] = [
            "product_id" => $key,
            "quantity" => $val['quantity'],
            "price" => $val['price'],
            "total" => $val['total'],
        ];
    }
    return $products;
}
print_r(getOldArray(getArray($products)));
READ ALSO
PHP определение кодировки

PHP определение кодировки

Есть скрипт что пытается определить кодировку и сменить на WINDOWS-1251Вот основной кусок:

651
Ajax игнорирует файл

Ajax игнорирует файл

Проект на LaravelЕсть форма с загрузкой файла

494
Кеширование картинок Nginx &amp; Laravel

Кеширование картинок Nginx & Laravel

Для кеширования картинок (nginx) у меня на сейте прописано правило:

497