【问题标题】:Merging two multidimensional arrays on specific key在特定键上合并两个多维数组
【发布时间】:2012-11-20 02:38:53
【问题描述】:

假设我有以下数组:

Array
    (
        [0] => Array
            (
                [id] => 5
                [name] => Education
            )

        [1] => Array
            (
                [id] => 4
                [name] => Computers
            )

        [3] => Array
            (
                [id] => 7
                [name] => Science

        [4] => Array
            (
                [id] => 1
                [name] => Sports
            )
    )

第二个:

Array
    (
        [0] => Array
            (
                [id] => 1
                [title] => Sport
            )

        [1] => Array
            (
                [id] => 7
                [title] => Sci
            )

        [3] => Array
            (
                [id] => 4
                [title] => Comp

        [4] => Array
            (
                [id] => 5
                [title] => Edu
            )
    )

所需的输出是:

Array
    (
        [0] => Array
            (
                [id] => 5
                [name] => Education
                [title] => Edu
            )

        [1] => Array
            (
                [id] => 4
                [name] => Computers
                [title] => Comp
            )

        [3] => Array
            (
                [id] => 7
                [name] => Science
                [title] => Sci

        [4] => Array
            (
                [id] => 1
                [name] => Sports
                [title] => Sport
            )
    )

我已经设法将这些数组合并为:

foreach($first as $key => $value){
    $result[$key] = array_merge($first[$key], $second[$key]);
}

但是输出没有正确组合:

Array
    (
        [0] => Array
            (
                [id] => 5
                [name] => Education
                [title] => Sport
            )

        [1] => Array
            (
                [id] => 4
                [name] => Computers
                [title] => Sci
            )

        [3] => Array
            (
                [id] => 7
                [name] => Science
                [title] => Comp

        [4] => Array
            (
                [id] => 1
                [name] => Sports
                [title] => Edu
            )
    )

问题是我想在同一个id 上合并这些数组。 所需的输出排序应与第一个数组中的相同。

我怎样才能做到这一点?非常感谢任何帮助。

【问题讨论】:

    标签: php multidimensional-array array-merge


    【解决方案1】:

    您可以只做一个嵌套循环并检查id 值是否匹配,然后将title 添加到$first(或name 到$second)

    foreach($first as $key => $value){
        foreach($second as $value2){
            if($value['id'] === $value2['id']){
                $first[$key]['title'] = $value2['title'];
            }               
        }
    }
    

    【讨论】:

    • 这个时间复杂度是多少? O(n^2)?绝对可以做得更好。
    【解决方案2】:

    您的代码工作正常。您的期望完全不正确。例如,在一个数组中,第 4 个元素 id 包含 1,但在另一个数组中,第 4 个元素 id 为 5,因此您的 “将这些数组合并到相同的 id” 与合并第 4 个元素没有任何意义元素合二为一,您还可以合并它们的子元素,并且由于两个数组中都使用了id,因此一旦值必须消失,因为数组中不能有两个相等的键。

    编辑

    您必须手动合并,因为 PHP 函数基于 keys 合并,而您想基于 content 进行合并:

    $result = array();
    foreach( $arrayA as $keyA => $valA ) {
      foreach( $arrayB as $keyB => $valB ) {
         if( $valA['id'] == $valB['id'] ) {
           $result[$keyA] = $valA + $valB;
    
           // or if you do not care output keys, just
           // $result[] = $valA + $valB;
         }
      }
    }
    

    【讨论】:

    • 我已经纠正了输出中的一些错误,对此深表歉意。我想要的是例如$first[0]['id'](等于5)在第二个数组中找到相同的id,这里是$second[4]['id'],并将它们合并到新数组中,如下所示:array('id'=>5, 'name'=>'Education', 'title'=>'Edu')。这不可能吗?
    • 像魅力一样工作,谢谢 :) 抱歉标题误导。
    • 找不到匹配项时没有提前breaking?
    【解决方案3】:

    在PHP 5.5+ 中提供一种替代方法。

    由于两个数组的顺序不一样,先用array_column通过id索引数组。

    这将允许您在id 索引数组上使用array_replace_recusrive。

    array_replace_recursive 将合并数组中与两个数组集的索引关联匹配的值。

    可选择使用array_values 重新索引数组,删除id 索引关联。

    示例https://3v4l.org/ndv2j

    $first = array_column($first, null, 'id');
    $second = array_column($second, null, 'id');
    $result = array_values(array_replace_recursive($first, $second));
    

    结果

    Array
    (
        [0] => Array
            (
                [id] => 5
                [name] => Education
                [title] => Edu
            )
    
        [1] => Array
            (
                [id] => 4
                [name] => Computers
                [title] => Comp
            )
    
        [2] => Array
            (
                [id] => 7
                [name] => Science
                [title] => Sci
            )
    
        [3] => Array
            (
                [id] => 1
                [name] => Sports
                [title] => Sport
            )
    
    )
    

    【讨论】:

      【解决方案4】:

      不要在foreach中使用foreach,如果数组那么大,可能会太慢。

      $idArray = array_column($secondArray,'title','id');
      foreach($firstArray as $key => $val){
        $firstArray[$key]['title'] = (isset($idArray[$val['id']])) ? $idArray[$val['id']] : 'some title';
      }
      

      【讨论】:

        【解决方案5】:

        这可以很容易地使用array_column 的三参数形式通过id 值重新索引您的second 数组,然后循环遍历first 数组,合并匹配@ 的内容987654329@ 值(如果存在):

        $second = array_column($second, null, 'id');
        foreach ($first as &$subject) {
            $subject = array_merge($subject, $second[$subject['id']] ?? []);
        }
        

        输出:

        Array
        (
            [0] => Array
                (
                    [id] => 5
                    [name] => Education
                    [title] => Edu
                )
            [1] => Array
                (
                    [id] => 4
                    [name] => Computers
                    [title] => Comp
                )
            [3] => Array
                (
                    [id] => 7
                    [name] => Science
                    [title] => Sci
                )
            [4] => Array
                (
                    [id] => 1
                    [name] => Sports
                    [title] => Sport
                )
        )
        

        Demo on 3v4l.org

        这比 Will B. 的不重新索引 first 数组的答案具有优势。它也稍微快一点(我的测试显示~10%),因为只有一个电话给array_column,而没有一个电话给array_values。

        更新

        通过使用array union operator (+) 可以进一步加快这段代码的速度(感谢@mickmackusa):

        $second = array_column($second, null, 'id');
        foreach ($first as &$subject) {
            $subject += $second[$subject['id']] ?? [];
        }
        

        这段代码的输出和上面一样,但是运行起来又快了10%左右。

        Demo on 3v4l.org

        【讨论】:

          【解决方案6】:

          然后确保项目的顺序相同:

          $items = array_map(function($itemFirstArray, $itemSecondArray) {
            return array_merge($itemFirstArray, $itemSecondArray);
          }, $firstArray, $secondArray);
          

          【讨论】:

          • 在确保两个数组正确排序的代码位上不进行 yatta-yatta 可能是有意义的。需要明确的是,这种技术要求两个数组都包含完全相同的 id 相关数据。
          【解决方案7】:

          按你的 'id' 字段对两个数组进行排序,然后让 php 与 array_replace_recursive 进行合并。

          function cmp($a, $b) {
            return ((int) $a['id'] < (int) $b['id']) ? -1 : 1;
          }
          
          usort($array1, 'cmp');
          usort($array2, 'cmp');
          
          $result = array_replace_recursive($array1, $array2);
          

          【讨论】:

          • 这个未经测试的 sn-p 在其输出中显然是不正确的。
          • 嘿@mickmackusa,很好发现。此代码适用于 array_replace_recursive,但不适用于 array_merge,显然!
          • 我仍然不推荐这种技术,因为与此页面上的其他答案相比,usort() 需要更高的计算复杂度。我有偏见,因为我已经与尼克合作,但是——我会使用尼克的回答。这假设两个数组都包含相同的卷和数据结构。它还要求两个数组共享相同的 id。这个答案对于一般用途来说是不可靠的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-27
          • 2016-12-14
          • 1970-01-01
          • 1970-01-01
          • 2014-03-08
          • 1970-01-01
          相关资源
          最近更新 更多