按数组值合并(并使用其他键进行计算)

时间:2017-08-18 12:43:20

标签: php arrays merge grouping

我很难找到解决此问题的可行解决方案:

这是我拥有的数组,我希望按product_name对此数组进行分组并计算数量。但阵列结构需要保持不变。

Array(
[0] => Array
    (
        [product_quantity] => 1
        [product_name] => Appel
    )

[1] => Array
    (
        [product_quantity] => 1
        [product_name] => D-Day
    )

[2] => Array
    (
        [product_quantity] => 4
        [product_name] => D-Day
    )

[3] => Array
    (
        [product_quantity] => 2
        [product_name] => D-Day
    )

[4] => Array
    (
        [product_quantity] => 1
        [product_name] => Emiel
    )

[5] => Array
    (
        [product_quantity] => 9
        [product_name] => Emiel
    )

[6] => Array
    (
        [product_quantity] => 3
        [product_name] => Estella
    )

[7] => Array
    (
        [product_quantity] => 4
        [product_name] => Feeke
    )

[8] => Array
    (
        [product_quantity] => 1
        [product_name] => Feeke
    )

[9] => Array
    (
        [product_quantity] => 7
        [product_name] => Reset
    )

[10] => Array
    (
        [product_quantity] => 1
        [product_name] => Reset
    ))

我需要输出:

Array(
    [0] => Array
        (
            [product_quantity] => 1
            [product_name] => Appel
        )

    [1] => Array
        (
            [product_quantity] => 7
            [product_name] => D-Day
        )

    [2] => Array
        (
            [product_quantity] => 10
            [product_name] => Emiel
        )

    [3] => Array
        (
            [product_quantity] => 3
            [product_name] => Estella
        )

    [4] => Array
        (
            [product_quantity] => 5
            [product_name] => Feeke
        )

    [5] => Array
        (
            [product_quantity] => 8
            [product_name] => Reset
        )
    )

我希望听到一些建议,或解决方法来解决这个问题!

2 个答案:

答案 0 :(得分:0)

我不测试它,但我认为它可以解决你的问题。

$stocks = [];

foreach ($products as $product) {
    if (isset($stocks[$product['product_name']])) {
        $stocks[$product['product_name']] += $product['product_quantity'];
    } else {
        $stocks[$product['product_name']] = $product['product_quantity'];
    }
}

$finalList = [];

foreach ($stocks as $key => $stock) {
    $finalList[] = [
        'product_quantity' => $stock,
        'product_name' => $key
    ];
}

print_r($finalList);

答案 1 :(得分:0)

可以通过多种方式实现目标。如果你的目标是速度,那么使用foreach迭代输入数组,逐步计算并将值存储到一个新数组(下面的回调函数体)。

如果您的目标是用您的PHP知识给您的同事或招聘人员留下深刻印象,请使用array_reduce()

$output = array_values(         // We don't need the keys of the generated array
    array_reduce(               // Incrementally process $input using a callback
        $input,
        // $carry is the partial result
        // $item is the currently processed item
        function(array $carry, array $item) {
            // Extract the product name into a local variable
            // we'll use it several times below
            $name = $item['product_name'];
            // If it's a new product then initialize its entry in the output
            if (! array_key_exists($name, $carry)) {
                $carry[$name] = array(
                    'product_quantity' => 0,
                    'product_name'     => $name,
                );
            }
            // Update the quantity of this group
            $carry[$name]['product_quantity'] += $item['product_quantity'];
            // Return the partial result
            return $carry;
        },
        // Start with an empty array
        array()
    )
);

更新

OP在评论中询问如何重用回调函数并使其可自定义(“如何使用参数使'product_name'动态化?”)。

您可以将值('product_name')放入函数外部的变量($key)中,并使用use language construct让匿名函数继承它。

$key = 'product_name';            // The values needs to be in a variable
$output = array_values(
    array_reduce(
        $input,
        // The 'use' keyword lets the anonymous function use a copy of $key
        function(array $carry, array $item) use ($key) {
            $name = $item[$key];
            // The rest of the callback's code comes here unchanged
            // ...
            // Return the partial result
            return $carry;
        },
        array()
    )
);

有关更多示例,请参阅Example #3文档中的anonymous functions

您可以将回调函数存储到变量中。除了代码的可读性之外,这并没有改进。但是,继续阅读,这只是一个中间步骤,真正的魔力发生在下面。

$key = 'abc';
$f = function(array $carry, array $item) use ($key) {
    $name = $item[$key];
    // The rest of the callback's code comes here unchanged
    // ...
    // Return the partial result
    return $carry;
};

$output = array_values(array_reduce($input, $f, array()));

为了使其真正可重用,您需要有一种方法来为$key的不同值生成回调。让我们编写一个创建参数化回调的简单函数:

// This function creates a new callback that uses the value of argument $key
function makeFn($key)
{
    return function(array $carry, array $item) use ($key) {
        $name = $item[$key];
        // The rest of the callback's code comes here unchanged
        // ...
        // Return the partial result
        return $carry;
    };
}

现在,让我们使用新功能。它创建了不同的回调函数,可以通过使用各种键来减少数组:

$output1 = array_values(array_reduce($input, makeFn('product_name'), array()));
$output2 = array_values(array_reduce($input, makeFn('product_code'), array()));