PHP - 如何合并数组内的数组

69
如何在PHP中合并n个数组。我的意思是如何像这样完成工作:
array_merge(from: $result[0], to: $result[count($result)-1])
OR
array_merge_recursive(from: $result[0], to: $result[count($result) -1])


其中$result是一个包含多个数组的数组,如下所示:
$result = Array(
0 => array(),//associative array
1 => array(),//associative array
2 => array(),//associative array
3 => array()//associative array
)

我的结果是:

$result = Array(
    0 => Array(
        "name" => "Name",
        "events" => 1,
        "types" => 2
    ),
    1 => Array(
        "name" => "Name",
        "events" => 1,
        "types" => 3
    ),
    2 => Array(
        "name" => "Name",
        "events" => 1,
        "types" => 4
    ),
    3 => Array(
        "name" => "Name",
        "events" => 2,
        "types" => 2
    ),
    4 => Array(
        "name" => "Name",
        "events" => 3,
        "types" => 2
    )
)

我需要的是什么

$result = Array(
"name" => "name",
"events" => array(1,2,3),
"types" => array(2,3,4)
)

不应该有任何区别。array_merge() + unset()(如果需要)。 - BlitZ
5
请描述您拥有的数据和您期望的结果,而不是伪代码函数签名。 - deceze
我同意deceze的看法,这个问题需要一个适当的[mcve]。如果这个问题被真正地解决了,这个页面可能会收到更多/更好的答案,并且可以用来关闭未来的重复问题。但现在,我认为这个问题不清楚。 - mickmackusa
看起来没有任何一个答案是基于名称列进行分组并从其余列生成子数组。如果这个页面不被直接删除,我建议重新关闭这个混乱的页面,使其成为“基于单列在2d数组中对行数据进行分组并将唯一数据推入各自的子数组”的标志。(https://stackoverflow.com/q/23109569/2943403) - mickmackusa
4个回答

201

array_merge 可以接收可变数量的参数,因此通过一些call_user_func_array 的技巧,你可以将你的 $result 数组传递给它:

$merged = call_user_func_array('array_merge', $result);

这基本上运行得像您键入:

$merged = array_merge($result[0], $result[1], .... $result[n]);

更新:

现在使用PHP 5.6,我们有了...运算符来将数组解包为参数,所以您可以:

$merged = array_merge(...$result);

并且有着相同的结果。*

* 只要在解压缩的数组中使用整数键,就会得到相同的结果;否则,您将收到一个E_RECOVERABLE_ERROR: type 4096 -- Cannot unpack array with string keys错误。


@complex857,我的情况是我有一个包含两个数组的数组[ array{array1, array2}],这些数组具有相同的参数,但我需要array{[0]=>array1的内容,[1]=>array2的内容}。在这种情况下,我应该进行哪些修改? - Nikita Dhiman
@NikitaDhiman,我不确定我能完全理解你的需求,但从这里看来,你需要使用foreach进行迭代,并通过手动构建所需的结构来实现。感觉你只是在结果周围多了一个额外的数组。 - complex857
@complex857,是的,情况确实如此...多了一个数组。更像是一个数组,其中结果包含两个内部包含相同类型数据的数组。其中的数据必须合并。 - Nikita Dhiman
在这种情况下,如果您知道键,则可以执行$result = $source [0],其中0是您拥有的键,如果您不知道该键,则可以使用reset()来获取数组的第一个元素(无论键如何),如下所示:$result = reset($source) - complex857
非常好的答案,但请注意 $merged = array_merge(...$result); 无法处理带有字符串键的数组。 - Robert Trzebiński
6
请注意,这实际上并没有产生问题中所期望的结果...!? - deceze

4

我非常喜欢complex857的回答,但它对我没有用,因为我的数组中有数字键需要保留。

我使用+运算符来保留键(如PHP array_merge with numerical keys中建议的),并使用array_reduce来合并数组。

因此,如果您想在保留数字键的情况下合并数组,则可以按以下方式执行:

<?php
$a = [
    [0 => 'Test 1'],
    [0 => 'Test 2', 2 => 'foo'],
    [1 => 'Bar'],
];    

print_r(array_reduce($a, function ($carry, $item) { return $carry + $item; }, []));
?>

结果:

Array
(
    [0] => Test 1
    [2] => foo
    [1] => Bar
)

4
如果您想要:
  • 检查传递到array_merge的每个参数是否实际上是数组
  • 指定要合并的一个数组中的特定属性
您可以使用以下函数:
function mergeArrayofArrays($array, $property = null)
{
    return array_reduce(
        (array) $array, // make sure this is an array too, or array_reduce is mad.
        function($carry, $item) use ($property) {

            $mergeOnProperty = (!$property) ?
                    $item :
                    (is_array($item) ? $item[$property] : $item->$property);

            return is_array($mergeOnProperty)
                ? array_merge($carry, $mergeOnProperty)
                : $carry;
    }, array()); // start the carry with empty array
}

让我们看看它的实际运用……这是一些数据:

简单结构:纯数组的数组可进行合并。

$peopleByTypesSimple = [
    'teachers' => [
            0  => (object) ['name' => 'Ms. Jo', 'hair_color' => 'brown'],
            1  => (object) ['name' => 'Mr. Bob', 'hair_color' => 'red'],
    ],

    'students' => [
            0  => (object) ['name' => 'Joey', 'hair_color' => 'blonde'],
            1  => (object) ['name' => 'Anna', 'hair_color' => 'Strawberry Blonde'],
    ],

    'parents' => [
            0  => (object) ['name' => 'Mr. Howard', 'hair_color' => 'black'],
            1  => (object) ['name' => 'Ms. Wendle', 'hair_color' => 'Auburn'],
    ],
];

稍微复杂一些:数组中的数组,但希望指定人员忽略数量

$peopleByTypes = [
    'teachers' => [
        'count' => 2,
        'people' => [
            0  => (object) ['name' => 'Ms. Jo', 'hair_color' => 'brown'],
            1  => (object) ['name' => 'Mr. Bob', 'hair_color' => 'red'],
        ]
    ],

    'students' => [
        'count' => 2,
        'people' => [
            0  => (object) ['name' => 'Joey', 'hair_color' => 'blonde'],
            1  => (object) ['name' => 'Anna', 'hair_color' => 'Strawberry Blonde'],
        ]
    ],

    'parents' => [
        'count' => 2,
        'people' => [
            0  => (object) ['name' => 'Mr. Howard', 'hair_color' => 'black'],
            1  => (object) ['name' => 'Ms. Wendle', 'hair_color' => 'Auburn'],
        ]
    ],
];

运行它。
$peopleSimple = mergeArrayofArrays($peopleByTypesSimple);
$people = mergeArrayofArrays($peopleByTypes, 'people');

结果 - 两者都返回这个:

Array
(
    [0] => stdClass Object
        (
            [name] => Ms. Jo
            [hair_color] => brown
        )

    [1] => stdClass Object
        (
            [name] => Mr. Bob
            [hair_color] => red
        )

    [2] => stdClass Object
        (
            [name] => Joey
            [hair_color] => blonde
        )

    [3] => stdClass Object
        (
            [name] => Anna
            [hair_color] => Strawberry Blonde
        )

    [4] => stdClass Object
        (
            [name] => Mr. Howard
            [hair_color] => black
        )

    [5] => stdClass Object
        (
            [name] => Ms. Wendle
            [hair_color] => Auburn
        )

)

额外的乐趣: 如果您想从一个人员数组(或关联数组)中提取一个属性,例如“名称”,您可以使用此函数。

function getSinglePropFromCollection($propName, $collection, $getter = true)
{
    return (empty($collection)) ? [] : array_map(function($item) use ($propName) {
        return is_array($item) 
            ? $item[$propName] 
            : ($getter) 
                ? $item->{'get' . ucwords($propName)}()
                : $item->{$propName}
    }, $collection);
}

getter是用来获取可能被保护/私有的对象的。

$namesOnly = getSinglePropFromCollection('name', $peopleResults, false);

返回:

Array
(
    [0] => Ms. Jo
    [1] => Mr. Bob
    [2] => Joey
    [3] => Anna
    [4] => Mr. Howard
    [5] => Ms. Wendle
)

0
尝试一下这个。
$result = array_merge($array1, $array2);

或者,你可以使用执行联合的 + 运算符来代替 array_merge:

$array2 + array_fill_keys($array1, '');

但我需要像这样的东西:array_merge($arr_1, $arr_2, ..., $arr_n),因为$result变量可能包含n个关联数组。有什么建议吗? - Lekhnath

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