PHP如何在相同的键和值上合并两个数组?

6
我有两个数组,希望将它们按照相同的键和值合并。如果它们具有相同的 ur_user_id,则进行合并。array2 仅提供了一些额外的数据给 array1,所以 new_array.length = array1.lengtharray1 只是从 array2 获取了额外的数据。
$array1 =    
    array(
        array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA'),
        array('ur_user_id'=> 2,'ur_fname'=>'PerB','ur_lname'=>'SonB'),
        array('ur_user_id'=> 3,'ur_fname'=>'PerC','ur_lname'=>'SonC'),
    );
$array2 = 
    array(
        array('ur_user_id' => 5,'ur_code' => 'EE','ur_user_role' => 'testE'),
        array('ur_user_id' => 4,'ur_code' => 'DD','ur_user_role' => 'testD'),
        array('ur_user_id' => 6,'ur_code' => 'FF','ur_user_role' => 'testF'),
        array('ur_user_id' => 3,'ur_code' => 'CC','ur_user_role' => 'testC'),
        array('ur_user_id' => 1,'ur_code' => 'AA','ur_user_role' => 'testA'),
        array('ur_user_id' => 2,'ur_code' => 'BB','ur_user_role' => 'testB'),
    );    

那么新数组必须看起来像这样。它将同时具有array1array2的值。

$new_array =    
    array(
        array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA','ur_code' => 'AA','ur_user_role' => 'testA'),
        array('ur_user_id'=> 2,'ur_fname'=>'PerB','ur_lname'=>'SonB','ur_code' => 'BB','ur_user_role' => 'testB'),
        array('ur_user_id'=> 3,'ur_fname'=>'PerC','ur_lname'=>'SonC','ur_code' => 'CC','ur_user_role' => 'testC'),
    );

array1.length 总是小于或等于 array2.length,永远不会大于。两个数组的顺序也不一定总是有序的。我尝试了下面这个函数,但它对我没有用,而且我不太擅长循环。

function merge_common_keys(){
    $arr = func_get_args();
    $num = func_num_args();

    $keys = array();
    $i = 0;
    for ($i=0; $i<$num; ++$i){
        $keys = array_merge($keys, array_keys($arr[$i]));
    }
    $keys = array_unique($keys);

    $merged = array();

    foreach ($keys as $key){
        $merged[$key] = array();
        for($i=0; $i<$num; ++$i){
            $merged[$key][] = isset($arr[$i][$key]) ? $arr[$i][$key] : null;
        }
    }
    return $merged;
}

基于给定的数组,结果如下。它只合并相同键的值。
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [ur_user_id] => 1
                    [ur_fname] => PerA
                    [ur_lname] => SonA
                )

            [1] => Array
                (
                    [ur_user_id] => 5
                    [ur_code] => AA-BB-CC
                    [ur_user_role] => testE
                )

        )

@NareshKumar 这是同一个键,而不是键内的值。 - Dev
@iamdevlinph 我无法明智地使用此页面关闭更新的页面,因为这里有太多有缺陷和间接的答案(因此,研究人员将浪费大量时间阅读不应使用的答案)。 - mickmackusa
5个回答

2
当您需要进行重复检查/搜索值(有效的唯一标识符)时,最有效的方法通常是:
1. 生成一个键控数组 2. 进行迭代调用`isset()`(而不是`in_array()`或`array_search()`)
`ur_user_id`是您的“唯一标识符”。 通过使用`array_column()`将`ur_user_id`值分配为键,从而准备了`$array2`。 `$array1`控制迭代次数。 我的方法将在使用联合运算符(`+=`)将`$array2`数据附加到`$array1`每个原始行之前,在`$array1`和`$array2`之间检查相应行(以避免“Notices”)。 foreach循环中的`&`“引用修饰符”--这意味着实际的输入数组正在被“处理”,而不是输入数组的“副本”。
代码:(演示)
$array1 =    
    array(
        array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA'),
        array('ur_user_id'=> 2,'ur_fname'=>'PerB','ur_lname'=>'SonB'),
        array('ur_user_id'=> 3,'ur_fname'=>'PerC','ur_lname'=>'SonC'),
    );
$array2 = 
    array(
        array('ur_user_id' => 5,'ur_code' => 'EE','ur_user_role' => 'testE'),
        array('ur_user_id' => 4,'ur_code' => 'DD','ur_user_role' => 'testD'),
        array('ur_user_id' => 6,'ur_code' => 'FF','ur_user_role' => 'testF'),
        array('ur_user_id' => 3,'ur_code' => 'CC','ur_user_role' => 'testC'),
        array('ur_user_id' => 1,'ur_code' => 'AA','ur_user_role' => 'testA'),
        array('ur_user_id' => 2,'ur_code' => 'BB','ur_user_role' => 'testB'),
    );  

$keyed = array_column($array2, NULL, 'ur_user_id'); // replace indexes with ur_user_id values

foreach ($array1 as &$row) {       // write directly to $array1 while iterating
    if (isset($keyed[$row['ur_user_id']])) { // check if shared key exists
        $row += $keyed[$row['ur_user_id']]; // append associative elements
    }
}

var_export($array1);

输出:

array (
  0 => 
  array (
    'ur_user_id' => 1,
    'ur_fname' => 'PerA',
    'ur_lname' => 'SonA',
    'ur_code' => 'AA',
    'ur_user_role' => 'testA',
  ),
  1 => 
  array (
    'ur_user_id' => 2,
    'ur_fname' => 'PerB',
    'ur_lname' => 'SonB',
    'ur_code' => 'BB',
    'ur_user_role' => 'testB',
  ),
  2 => 
  array (
    'ur_user_id' => 3,
    'ur_fname' => 'PerC',
    'ur_lname' => 'SonC',
    'ur_code' => 'CC',
    'ur_user_role' => 'testC',
  ),
)

这对我来说非常有效。 现在我面临的问题是,如果不存在一个键,我想添加一个空键和值对。应该怎么做? - golchha21
1
@golchha21 当您提出新问题时,请创建一些设置问题的示例数组。展示您的编码尝试。然后展示您所期望的精确输出。 - mickmackusa
1
@golchha21 你是指像这样的吗?https://3v4l.org/ojJZ9 没有完整的问题描述,很难猜测你所期望的行为/输出。 - mickmackusa
嘿@mickmackusa,谢谢你的提问,但我已经通过循环使用我生成的主数组来获得所需的结果。 - golchha21
这个问题不是我的。所以我不能接受或拒绝答案。 此外,您提供的答案已被我点赞,而被接受的答案则被踩了。 - golchha21
哦,对不起,我没注意到。 - mickmackusa

1

试试这个:

<?php

$array1 =    
    array(
        array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA'),
        array('ur_user_id'=> 2,'ur_fname'=>'PerB','ur_lname'=>'SonB'),
        array('ur_user_id'=> 3,'ur_fname'=>'PerC','ur_lname'=>'SonC'),
    );
$array2 = 
    array(
        array('ur_user_id' => 5,'ur_code' => 'EE','ur_user_role' => 'testE'),
        array('ur_user_id' => 4,'ur_code' => 'DD','ur_user_role' => 'testD'),
        array('ur_user_id' => 6,'ur_code' => 'FF','ur_user_role' => 'testF'),
        array('ur_user_id' => 3,'ur_code' => 'CC','ur_user_role' => 'testC'),
        array('ur_user_id' => 1,'ur_code' => 'AA','ur_user_role' => 'testA'),
        array('ur_user_id' => 2,'ur_code' => 'BB','ur_user_role' => 'testB'),
    );


$result = array();

$userIdsFromArray1 = array_column($array1, 'ur_user_id');


foreach($array2 as $subarray)
{
    if(in_array($subarray['ur_user_id'], $userIdsFromArray1))
    {
        $result[] = array_merge($subarray, getDataFromArray1ByUserId($array1, $subarray['ur_user_id']));
    }
}


function getDataFromArray1ByUserId($array1, $userId)
{
    foreach($array1 as $key => $data)
    {
        if($data['ur_user_id'] == $userId)
            return $data;
    }

    return array();
}

 usort($result,function($a,$b){
    return strnatcmp($a['ur_user_id'],$b['ur_user_id']);
});

print_r($result);

工作示例: 点击!

“尝试这个”(仅代码)类型的答案在 StackOverflow 上的价值较低,因为它们对于教育/赋能提问者和未来的研究者帮助不大。每次回答时,请附上一些解释,以使您的解决方案(以及该网站)更有价值。 - mickmackusa

1

试用这段代码,它可能有所帮助,而且短小精悍,不需要遍历循环:

    usort($array2,function($a,$b){
        return strnatcmp($a['ur_user_id'],$b['ur_user_id']);
    });
    $array3 = array_replace_recursive($array1, $array2);

    $result = array_uintersect($array3,$array1,function($a,$b){
        return strnatcmp($a['ur_user_id'],$b['ur_user_id']);
    });
    print_r($result);

输出

Array
(
    [0] => Array
        (
            [ur_user_id] => 1
            [ur_fname] => PerA
            [ur_lname] => SonA
            [ur_code] => AA
            [ur_user_role] => testA
        )

    [1] => Array
        (
            [ur_user_id] => 2
            [ur_fname] => PerB
            [ur_lname] => SonB
            [ur_code] => BB
            [ur_user_role] => testB
        )

    [2] => Array
        (
            [ur_user_id] => 3
            [ur_fname] => PerC
            [ur_lname] => SonC
            [ur_code] => CC
            [ur_user_role] => testC
        )

)

这里是演示

(保留HTML标签)

避免循环并不一定是一个优势。我认为对于这个任务来说,排序是一个不必要的步骤。当array1的前3个子数组不是array2的前3个子数组时,你的答案将会出错。证明:https://3v4l.org/7unT8 array_replace_recursive() 对于这个任务来说并不是一个非常直接的方法,并且它没有被正确实现。 - mickmackusa
这个解决方案仅限于2个数组。 我尝试将其放入循环中,但它没有起作用。 - golchha21

1

在foreach循环中尝试使用以下三行代码:

$array1 =    
    array(
        array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA'),
        array('ur_user_id'=> 2,'ur_fname'=>'PerB','ur_lname'=>'SonB'),
        array('ur_user_id'=> 3,'ur_fname'=>'PerC','ur_lname'=>'SonC'),
    );
$array2 = 
    array(
        array('ur_user_id' => 5,'ur_code' => 'EE','ur_user_role' => 'testE'),
        array('ur_user_id' => 4,'ur_code' => 'DD','ur_user_role' => 'testD'),
        array('ur_user_id' => 6,'ur_code' => 'FF','ur_user_role' => 'testF'),
        array('ur_user_id' => 3,'ur_code' => 'CC','ur_user_role' => 'testC'),
        array('ur_user_id' => 1,'ur_code' => 'AA','ur_user_role' => 'testA'),
        array('ur_user_id' => 2,'ur_code' => 'BB','ur_user_role' => 'testB'),
    );

$newArray =array(); 

foreach($array1 as $key => $val)
{
    $ids = array_map(function ($ar) {return $ar['ur_user_id'];}, $array2); //get the all the user ids from array 2
    $k = array_search($val['ur_user_id'],$ids); // find the key of user id in ids array
    $newArray[] = array_merge($array1[$key],$array2[$k]); /// merge the first array key with second
}   

echo "<pre>"; print_r($newArray);

这将给你:
(
    [0] => Array
        (
            [ur_user_id] => 1
            [ur_fname] => PerA
            [ur_lname] => SonA
            [ur_code] => AA
            [ur_user_role] => testA
        )

    [1] => Array
        (
            [ur_user_id] => 2
            [ur_fname] => PerB
            [ur_lname] => SonB
            [ur_code] => BB
            [ur_user_role] => testB
        )

    [2] => Array
        (
            [ur_user_id] => 3
            [ur_fname] => PerC
            [ur_lname] => SonC
            [ur_code] => CC
            [ur_user_role] => testC
        )

)

实时演示



foreach() 的每次迭代中,您不应该重新映射 $ids。这个解决方案并不是很精细/高效。为什么要使用 $array1[$key],而不是 $val - mickmackusa

-1
你最好选择这个: 工作示例
$ids = array();
$out = array();
foreach($array1 as $key => $value){
    if(isset($array2[$key]))
        $out[$key][] = $array2[$key];
    $out[$key][] = $value;
    $ids[] = $array2[$key]['ur_user_id'];
}

foreach($array2 as $key => $val){
    if(!in_array($val['ur_user_id'], $ids))
        $out[$key][] = $array2[$key];
}

它没有来自array1array2的两个值。合并后,它应该看起来像这样:array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA','ur_code' => 'AA','ur_user_role' => 'testA') - Dev
那么你需要匹配索引吗?那么array2的其余元素怎么办? - Murad Hasan
array2array1提供了一些额外的信息。因此,基础仅仅是array1 - Dev
每个 Stackoverflow 的答案都应该包含解释。不要假设您知道将来访问此页面的每个研究者的知识水平。这个网站是一个教育资源...不仅仅是针对 OP,也是针对其他读者。从来没有一个只有代码的答案是好的理由。 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接