【问题标题】:Merging by array value (and doing calculations with the other keys)按数组值合并(并使用其他键进行计算)
【发布时间】:2018-01-27 03:49:56
【问题描述】:

我很难为这个问题找到可行的解决方案:

这是我拥有的数组,我想将这个数组按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
        )
    )

我很想听听一些关于如何解决这个问题的建议或解决方案!

【问题讨论】:

  • array_reduce() PHP 函数的完美示例。
  • 嗨 axiac,感谢您的快速回复。以前没听说过。回调函数需要是什么?或者你能帮助我朝着正确的方向前进吗?

标签: php arrays merge grouping


【解决方案1】:

可以通过多种方式实现目标。如果您的目标是速度,则使用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()
    )
);

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

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

$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()));

【讨论】:

  • 好人!快速,工作正常!需要分析这个以备将来使用:) 非常感谢!
  • 嗨 axiac,关于这个的快速问题。我一直在不同的用例中使用它。但是如何使用参数动态地制作“product_name”?我想向封闭函数发送一个参数,该函数可以像这样更改密钥 -> $name = $item[customParam];
  • 将值放入函数外的变量($customParam = 'product_name';),并使用use language construct让匿名函数继承它(function(array $carry, array $item) use ($customParam) { $name = $item[$customParam]; ...})。请参阅 anonymous functions 的文档中的 Example #3
  • 这就是我想要的!再次感谢:-)
【解决方案2】:

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

$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);

【讨论】:

  • 应该可以,但是为什么要使用两个循环呢?您可以在第一个foreach 中存储$stocks 中的名称和数量。它的运行速度会快两倍。
  • 数组 ( [Appel] => 1 [D-Day] => 7 [Emiel] => 10 [Estella] => 3 [Feeke] => 5 [Reset] => 8 ) 然后我得到这个输出
  • @axiac 你是对的,但它只是快速而肮脏的版本。顺便说一句,您可以在第一个循环中执行此操作,但这会有点棘手,因为您希望最后有一个顺序数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-25
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
相关资源
最近更新 更多