如果数组的值匹配,则聚合多级数组中的数组


Aggregate arrays in multilevel array if their values match

我有一个以下格式的数组:

array(5){
    [0] =>
    array(4){
        ['product-id'] => 8931
        ['product'] => 'Cake'
        ['description'] => 'Yellow cake'
        ['quantity'] => 1
    }
    [1] =>
    array(4){
        ['product-id'] => 8921
        ['product'] => 'Cookies'
        ['description'] => 'Chocolate chip cookies'
        ['quantity'] => 2
    }   
    [2] =>     
    array(4){
        ['product-id'] => 8931
        ['product'] => 'Cake'
        ['description'] => 'Yellow cake'
        ['quantity'] => 1
    }        
    [3] =>
    array(4){
        ['product-id'] => 8931
        ['product'] => 'Cake'
        ['description'] => 'Yellow cake'
        ['quantity'] => 4
    }     
    [4] =>   
    array(4){
        ['product-id'] => 8933
        ['product'] => 'Cake'
        ['description'] => 'Chocolate cake'
        ['quantity'] => 1
    }
}

如何将所有阵列相互比较?在我的代码中,我已经按产品ID对所有数组进行了排序,并编写了一个for来一次比较两行,但现在我明白了为什么这不起作用。

function cmp($a, $b){
    return strcmp($a[0], $b[0]);
}
function combineArrays($arrays){
    usort($arrays, "cmp");
    for($i = 1; $i < count($arrays); $i++){
        $f_row = $arrays[$i];
        $next = $i + 1;
        $s_row = $arrays[$next];
        if($f_row[0] == $s_row[0]){
            if($f_row[1] == $s_row[1]){
                if($f_row[2] == $s_row[2]){
                                    $q1 = (int) $f_row[3];
                                    $q2 = (int) $s_row[3];
                                    $total = $q1 + $q2;
                                    unset($f_row[3]);
                                    $f_row[5] = $total;
                                    unset($arrays[$next]);
                }
            }
        }
    }
    return $arrays;
}

有什么更好的方法可以做到这一点?

例如,要获取第一个数组并将其与下一个数组进行比较,请逐个值。一旦前3个值中有一个不匹配,就继续将该行与下一行进行比较。如果前三个值都匹配,则将两个数组的数量值相加,将其分配给第一个数组的量,然后去掉第二个数组。可能会有更多的匹配,所以继续比较该数组,直到您浏览完整个列表。

我最喜欢的解决方案使用array_reduce():

$filtered = array_reduce(
    // Reduce the original list
    $arrays,
    // The callback function adds $item to $carry (the partial result)
    function (array $carry, array $item) {
        // Generate a key that contains the first 3 properties
        $key = $item['product-id'].'|'.$item['product'].'|'.$item['description'];
        // Search into the partial list generated until now
        if (array_key_exists($key, $carry)) {
            // Update the existing item
            $carry[$key]['quantity'] += $item['quantity'];
        } else {
            // Add the new item
            $carry[$key] = $item;
        }
        // The array_reduce() callback must return the updated $carry
        return $carry;
    },
    // Start with an empty list
    array()
);

尝试这个

$arr=array(
    array(
        'product-id' => 8931,
        'product' => 'Cake',
        'description' => 'Yellow cake',
        'quantity' => 3,
    ),
    array(
        'product-id' => 8921,
        'product' => 'Cookies',
        'description' => 'Chocolate chip cookies',
        'quantity' => 2,
    ),  
    array(
        'product-id' => 8931,
        'product' => 'Cake',
        'description' => 'Yellow cake',
        'quantity' => 1,
    )      
);
$id = array();
foreach ($arr as $key => $row)
{
    $id[$key] = $row['product-id'];
}
array_multisort($id, SORT_DESC, $arr);
$result = array();
foreach ($arr as $key => $row)
{
    $pid = $row['product-id'];
    if(!isset($result[$pid]))
    {
        $result[$pid]=$row;
    }else{
        $result[$pid]['quantity']+=$row['quantity'];
    }
}
print_r($result);

你做得很艰难,为什么不这样做呢:

function combineProducts($products) {
    $result = array();
    foreach ($products as $product) {
        //if you can have different product or descriptions
        //per product id you can change this this to
        //$productId = implode('|', array($product['product-id'], $product['product'], $product['description']);
        $productId = $product['product-id'];
        //check if we already have this product
        if (isset($result[$productId])) {
            //add to the quantity
            $result[$productId]['quantity']+= $product['quantity'];
        } else {
            $result[$productId] = $product;
        }
    }
    //sort the results (remove if not needed)
    ksort($result);
    //return values (change to return $result; if you want an assoc array)
    return array_values($result);
}