【问题标题】:Merge multiple multidimensional arrays and group by id column合并多个多维数组并按 id 列分组
【发布时间】:2015-11-18 04:39:56
【问题描述】:

我有以下3个多维数组:

Array
(
    [0] => Array
        (
            [id_produto] => 191
            [categoria] => 7
            [prazo] => 8
            [desconto] => 45
        )

    [1] => Array
        (
            [id_produto] => 194
            [categoria] => 7
            [prazo] => 8
            [desconto] => 39
        )

    [2] => Array
        (
            [id_produto] => 195
            [categoria] => 7
            [prazo] => 8
            [desconto] => 39
        )


Array
(
    [0] => Array
        (
            [id_produto] => 191
            [categoria] => 7
            [pageviews] => 2103
        )

    [1] => Array
        (
            [id_produto] => 194
            [categoria] => 7
            [pageviews] => 2445
        )

    [2] => Array
        (
            [id_produto] => 195
            [categoria] => 7
            [pageviews] => 1560
        )

Array
(
    [0] => Array
        (
            [id_produto] => 191
            [categoria] => 7
            [pedidos] => 3
            [valor] => 6501.583023
        )

    [1] => Array
        (
            [id_produto] => 194
            [categoria] => 7
            [pedidos] => 1
            [valor] => 2217.968420
        )

    [2] => Array
        (
            [id_produto] => 197
            [categoria] => 7
            [pedidos] => 2
            [valor] => 4405.517706
        )

我想将它们结合起来,保留键 'id_produto' 和 'categoria' 并有类似的东西:

Array
(
    [0] => Array
        (
            [id_produto] => 191
            [categoria] => 7
            [prazo] => 8
            [desconto] => 45
            [pageviews] => 2103
            [pedidos] => 3
            [valor] => 6501.583023
        )

    [1] => Array
        (
            [id_produto] => 194
            [categoria] => 7
            [prazo] => 8
            [desconto] => 39
            [pageviews] => 2445
            [pedidos] => 1
            [valor] => 2217.968420
        )

    [2] => Array
        (
            [id_produto] => 195
            [categoria] => 7
            [prazo] => 8
            [desconto] => 39
            [pageviews] => 1560
            [pedidos] => 2
            [valor] => 4405.517706
        )

我尝试了array_merge($array1,$array2,$array3)array_merge_recursive($array1,$array2,$array3),但它确实将它们复制到一个包含 9 个元素的数组中。以下代码对我有用,但我正在寻找更快的解决方案,因为我有数千个 ID:

foreach($array1 as $arr1=>$a){
    foreach($array2 as $arr2=>$b){
        if($a['id_produto'] == $b['id_produto']){
            $array1[$arr1]['pageviews'] = $b['pageviews'];
        }
    }
    foreach($array3 as $arr3=>$c){
        if($a['id_produto'] == $c['id_produto']){
            $array1[$arr1]['pedidos'] = $c['pedidos'];
            $array1[$arr1]['valor'] = $c['valor'];
        }
    }
}

【问题讨论】:

  • 您确定所有 3 个数组的顺序相同吗?同上显示您尝试过的代码,即使它不起作用!
  • 我编辑了我的问题。我基本上尝试像在其他问题中发现的那样应用 array_merge,但没有运气。也许还有另一个 php 函数可以处理这个问题。我可以尝试的一件事是遍历它们,但这是我最后的手段。
  • 我可以订购它们,但不能保证所有 id 都在所有 3 个数组中

标签: php arrays multidimensional-array merge grouping


【解决方案1】:

首先,为什么您的代码很慢?假设您有 1000 个元素,您的代码正在执行 1000*(1000+1000) = 200 万次迭代。这就是为什么。

如何让它更快?使用 assoc 数组 而不是普通数组,即使用 id_produto 作为键,这样您就可以直接访问正确的元素,而不必在循环中执行循环。

为此,首先转换array2 和array3。 array2 示例:

$new_array2 = array();
foreach ( $array2 as $row ) {
    $new_array2[$row['id_produto']] = $row;
}
$array2 = $new_array2;

然后合并:

foreach ( $array1 as & $row ) {
    $row['pageviews'] = $array2[$row['id_produto']['pageviews']];
    $row['pedidos'] = $array3[$row['id_produto']['pedidos']];
    $row['valor'] = $array3[$row['id_produto']['valor']];
}

总计:仅 3000 次迭代。

【讨论】:

  • 注意:您可以将第一个 foreach 循环替换为 array_column($array2, null, 'id_produto') (more info)
【解决方案2】:

这可能有用:

$merged = array_merge($a, $b, $c);
$fixed_merge = Array();
for($i=0; $i < count($merged); $i++){
    echo $i;
    $this_id = $merged[$i]['id_produto'];
    if(isset($fixed_merge[$this_id])){
        $fixed_merge[$this_id] = array_merge($fixed_merge[$this_id], $merged[$i]);
    }else{
        $fixed_merge[$this_id] = $merged[$i];
    }
}
print_r($fixed_merge);

【讨论】:

    【解决方案3】:

    使用id_produto 键入您的数组,然后简单地使用 php 的内置数组函数,例如

    array_replace_recursive($one, $two, $three)
    

    【讨论】:

    • 谢谢,这是最简单的解决方案,没有 for-s 或 foreach-s 并且适用于数组大小
    • 这个 + array_column() 用于重新键入 = 不需要 foreach 循环
    • 这个答案不正确。它不会正确尊重数字键。这个未经测试的答案正在破坏 Stack Overflow 知识库。
    • 证明:3v4l.org/ZbcF5 产品 195 已损坏/与 197 合并。
    【解决方案4】:

    我将使用id_produto 为临时键填充第一个数组的结果数组。

    在循环中,您可以合并安全关联的行数据,同时按这些临时键进行分组。循环后,用array_values()重新索引结果数组。

    代码:(Demo) (Demo version 2 -- 可能更慢)

    $result = array_column($array1, null, 'id_produto');
    foreach (array_merge($array2, $array3) as $row) {
        $result[$row['id_produto']] = array_merge($result[$row['id_produto']] ?? [], $row);
    }
    var_export(array_values($result));
    

    这种方法将比@rlanvin 的答案进行更多的函数调用(因此它的性能应该稍慢),但不明确命名特定数组中的特定目标列的优点是这个 sn-p 不需要每次修改传入数组的数量和质量时都会更改。

    这个解决方案在 n 上有一个很大的 O。如果这三个数组有 1000 行,那么 array_column() 将迭代 1000 次而没有迭代函数调用。然后foreach() 将迭代 2000x 并每次调用array_merge()(可能将当前行与空数组合并)。因此,如果您拥有数百万行数据,则只会有数百万次迭代。

    以上也可以转化为功能迭代。 (Demo)

    var_export(
        array_values(
            array_reduce(
                array_merge($array2, $array3),
                function($result, $row) {
                    $result[$row['id_produto']] = array_merge($result[$row['id_produto']] ?? [], $row);
                    return $result;
                },
                array_column($array1, null, 'id_produto')
            )
        )
    );
    

    此外,您也可以使用本机递归函数。我不知道它在性能方面的比较,但可读性可以说比其他选项更好。

    代码:(Demo)

    var_export(
        array_values(
            array_replace_recursive(
                array_column($array1, null, 'id_produto'),
                array_column($array2, null, 'id_produto'),
                array_column($array3, null, 'id_produto')
            )
        )
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多