【问题标题】:PHP merge array with similar keys, and sum some keysPHP合并具有相似键的数组,并对一些键求和
【发布时间】:2021-01-10 13:32:28
【问题描述】:

在打扰这个令人敬畏的社区之前,我真的为此苦苦挣扎了一天多,但我没有任何运气。

我有一个看起来像这样的数组

$Data = [
  [
   'code' => 'P-01',
   'firstname' => 'Sam',
   'lastname' => 'Bouchard',
   'quantity' => 3
  ],
 [
   'code' => 'P-09',
   'firstname' => 'Roy',
   'lastname' => 'Gauthier',
   'quantity' => 14
  ],
 [
   'code' => 'P-24',
   'firstname' => 'Marin',
   'lastname' => 'Fortin',
   'quantity' => 24
  ],
 [
   'code' => 'P-03',
   'firstname' => 'Sam',
   'lastname' => 'Bouchard',
   'quantity' => 7
  ],
 [
   'code' => 'P-01',
   'firstname' => 'Sam',
   'lastname' => 'Bouchard',
   'quantity' => 9
  ],
];

所以我想合并数组所以我有这样的数组

$Data = [
  [
   'firstname' => 'Sam',
   'lastname' => 'Bouchard',
   'combined' => [
     'code' => 'P-01',
     'quantity' => 12 
   ],
   [
     'code'=> 'P-03',
     'quantity' => 7
   ]
  ],
  [
   'firstname' => 'Roy',
   'lastname' => 'Gauthier',
   'combined' => [
     'code' => 'P-09',
     'quantity' => 14 
   ]
  ],
  [
   'firstname' => 'Marin',
   'lastname' => 'Fortin',
   'combined' => [
     'code' => 'P-24',
     'quantity' => 24
   ]
  ],
];

如您所见,如果“代码”相同,我需要对数量求和。 提前致谢

【问题讨论】:

  • 向我们展示您的尝试、最佳尝试(代码)以及您遇到的问题。你得到什么错误?建议你阅读How to Ask
  • 这很容易通过几个循环来完成,见下文。但是,@jibsteroos 是对的,所以通常要求您至少尝试解决您的问题 - 即使您没有接近接近! - 我们的宗旨是帮助修复而不是为你写作
  • 我在这里解决了pastebin.com/D0vw3Na5

标签: php multidimensional-array array-merge


【解决方案1】:

在以下示例中,您将获得具有唯一代码键的新合并数组。此外,它会将前面的数量添加到后面的数量中。

$Merged = [];
foreach ($Data as $value) {
  if (isset($Merged[$value['code']])) {
    $Merged[$value['code']]['quantity'] += $value['quantity'];
  } else {
    $Merged[$value['code']] = $value;
  }
}

输出

Array
(
    [P-01] => Array
        (
            [code] => P-01
            [firstname] => Sam
            [lastname] => Bouchard
            [quantity] => 12
        )

    [P-09] => Array
        (
            [code] => P-09
            [firstname] => Roy
            [lastname] => Gauthier
            [quantity] => 14
        )

    [P-24] => Array
        (
            [code] => P-24
            [firstname] => Marin
            [lastname] => Fortin
            [quantity] => 24
        )

    [P-03] => Array
        (
            [code] => P-03
            [firstname] => Sam
            [lastname] => Bouchard
            [quantity] => 7
        )

)

【讨论】:

  • 格式不对?该问题需要组合名称和数量,即P-01 == P-03
  • @Steven 我认为他的目的是总结数量
  • 是的,我同意这看起来是主要目标。但在 OP 的 输出 中,他似乎也按名称分组?
  • @Steven 以他想要的方式提及。名字和姓氏与代码在同一个数组中。
【解决方案2】:

输入数据

请注意,您显示的数组在格式上有一些错误(可能是拼写错误)。我们将使用:

$data = [
  [
   'code' => 'P-01',
   'firstname' => 'Sam',
   'lastname' => 'Bouchard',
   'quantity' => 3
  ],
 [
   'code' => 'P-09',
   'firstname' => 'Roy',
   'lastname' => 'Gauthier',
   'quantity' => 14
  ],
 [
   'code' => 'P-24',
   'firstname' => 'Marin',
   'lastname' => 'Fortin',
   'quantity' => 24
  ],
 [
   'code' => 'P-03',
   'firstname' => 'Sam',
   'lastname' => 'Bouchard',
   'quantity' => 7
  ],
 [
   'code' => 'P-01',
   'firstname' => 'Sam',
   'lastname' => 'Bouchard',
   'quantity' => 9
  ]
];

变换数组

首先,我们要将数组转换为我们可以轻松使用的数据结构,同时我们可以组合和更新数量。

在这种情况下,我们将在三个级别上重新组织索引firstname -> lastname -> code

// Define the array for output of transformation
$firstnameIndexArray = [];

// Loop through all current data points
foreach($data as $point){

    // Set a pointer by reference to decrease the length of the next line(!) hopefully 
    // making it more readable
    $pointer   = &$firstnameIndexArray[$point['firstname']][$point['lastname']][$point['code']];

    // Update the quantity
    // $pointer ?? 0... sets to 0 if $pointer doesn't contain a value/exist
    $pointer   = ($pointer ?? 0) + $point["quantity"];
}

现在我们已经完成了一个数组,如下所示:

Array
(
    [Sam] => Array
        (
            [Bouchard] => Array
                (
                    [P-01] => 12
                    [P-03] => 7
                )

        )

    [Roy] => Array
        (
            [Gauthier] => Array
                (
                    [P-09] => 14
                )

        )

    [Marin] => Array
        (
            [Fortin] => Array
                (
                    [P-24] => 24
                )

        )

)

以正确的格式重新制作数组

现在剩下要做的就是遍历转换后的数组并以我们选择的格式输出...

// Define the output array
$finalArray = [];

// Loop through first level of array
foreach($firstnameIndexArray as $firstname => $lastnameIndexarray){

    // Loop through second level of array
    foreach($lastnameIndexarray as $lastname => $codeIndexArray){

        // Define the combined array of code/value pairs
        $combinedArray = [];

        // Loop though each code/value pair
        foreach($codeIndexArray as $code => $quantity){

            // Make the combined array in the correct format
            $combinedArray[] = [
                'code'     => $code,
                'quantity' => $quantity
            ];
        }

        // Add the person to the final array
        $finalArray[] = [
            'firstname' => $firstname,
            'lastname' => $lastname,
            'combined' => $combinedArray
        ];
    }
}

输出如下:

Array
(
    [0] => Array
        (
            [firstname] => Sam
            [lastname] => Bouchard
            [combined] => Array
                (
                    [0] => Array
                        (
                            [code] => P-01
                            [quantity] => 12
                        )

                    [1] => Array
                        (
                            [code] => P-03
                            [quantity] => 7
                        )

                )

        )

    [1] => Array
        (
            [firstname] => Roy
            [lastname] => Gauthier
            [combined] => Array
                (
                    [0] => Array
                        (
                            [code] => P-09
                            [quantity] => 14
                        )

                )

        )

    [2] => Array
        (
            [firstname] => Marin
            [lastname] => Fortin
            [combined] => Array
                (
                    [0] => Array
                        (
                            [code] => P-24
                            [quantity] => 24
                        )

                )

        )

)

没有 cmets 的代码

$firstnameIndexArray = [];
foreach($data as $point){
    $pointer   = &$firstnameIndexArray[$point['firstname']][$point['lastname']][$point['code']];
    $pointer   = ($pointer ?? 0) + $point["quantity"];
}

$finalArray = [];
foreach($firstnameIndexArray as $firstname => $lastnameIndexarray){
    foreach($lastnameIndexarray as $lastname => $codeIndexArray){
        $combinedArray = [];
        foreach($codeIndexArray as $code => $quantity){
            $combinedArray[] = [
                'code'     => $code,
                'quantity' => $quantity
            ];
        }
        $finalArray[] = [
            'firstname' => $firstname,
            'lastname' => $lastname,
            'combined' => $combinedArray
        ];
    }
}

【讨论】:

    【解决方案3】:

    可能的方法是使用“代码”作为新数组的索引:

    创建一个新的结果数组

    $combined = [];
    

    遍历 $Data 并将每个项目放入 $item 对于每个 $item 获取代码为 $key 检查你是否已经在组合数组中有一个值与该 $key

    if (isset($combined[$key]))) {...}
    

    如果没有,则使用该 $key 将项目添加到数组中

    $newItem = $this->createNewStructureFromItem($item);
    $combined[$key] = $newItem;
    

    如果您已经在组合数组中拥有该键,则仅更新数量

    $existingItem = $combined[$key];
    $updatedItem = $this->increaseQuantity($existingItem, $item);
    $combined[$key] = $updatedItem;
    

    【讨论】:

      猜你喜欢
      • 2016-01-19
      • 1970-01-01
      • 2021-10-09
      • 2014-03-12
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 2011-08-18
      • 1970-01-01
      相关资源
      最近更新 更多