根据共享列值将二维数组中的列值附加到另一个二维数组的行

问题描述 投票:0回答:7

假设我有以下数组:

$first = [
    ['id' => 5, 'name' => 'Education'],
    ['id' => 4, 'name' => 'Computers'],
    ['id' => 7, 'name' => 'Science'],
    ['id' => 1, 'name' => 'Sports'],
];

$second = [
    ['id' => 1, 'title' => 'Sport'],
    ['id' => 7, 'title' => 'Sci'],
    ['id' => 4, 'title' => 'Comp'],
    ['id' => 5, 'title' => 'Edu'],
];

期望的输出是:

[
    ['id' => 5, 'name' => 'Education', 'title' => 'Edu'],
    ['id' => 4, 'name' => 'Computers', 'title' => 'Comp'],
    ['id' => 7, 'name' => 'Science', 'title' => 'Sci'],
    ['id' => 1, 'name' => 'Sports', 'title' => 'Sport'],
]

我已经成功地简单地合并了这些数组:

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

但是输出是由第一级索引而不是它们的

id
值组合的:

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
7个回答
11
投票

您可以执行嵌套循环并检查

id
值是否匹配,然后将
title
添加到
$first
(或将
name
添加到
$second

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

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;
     }
  }
}

2
投票

提供

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
        )

)

1
投票

不要在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';
}

1
投票

这可以轻松完成,使用

array_column
的 3 参数形式,通过
second
值重新索引
id
数组,然后循环
first
数组,合并匹配
 的内容second
值(如果存在):

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

3v4l.org 上的演示

这比 Will B. 的答案(不重新索引

first
数组)有优势。由于只有一次对
array_column
的调用,并且没有对
array_values
的调用,它的速度也稍快一些(我的测试显示 ~10%)。

更新

实际上可以通过使用 数组联合运算符

+
)(感谢@mickmackusa)来加快这段代码的速度:

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

这段代码的输出与上面相同,但运行速度又快了 10% 左右。

3v4l.org 上的演示


0
投票

确保项目的顺序相同:

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

0
投票

按“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);
© www.soinside.com 2019 - 2024. All rights reserved.