合并两个数值键关联数组并保留原始键。

107

我有两个这样的数组:

array( 
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44'
);

array( 
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);

我想要将这两个数组合并,使它们不包含重复项,并保留它们的原始键。例如输出应为:

array( 
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);

我试过了,但它会改变它们的原始键:

$output = array_unique( array_merge( $array1 , $array2 ) );

有什么解决方案吗?

11个回答

194

只需使用:

$output = array_merge($array1, $array2);

这应该就能解决问题了。因为你使用的是字符串键,所以如果一个键出现多次(例如在你的示例中的'44'),后面的键会覆盖前面相同名称的键。由于它们都具有相同的值,所以并不重要,这也将删除重复项。

更新:我刚意识到 PHP 将数字字符串键作为数字(整数)处理,所以会表现出这种行为,也就是重新编号键...

解决方法是重新创建键。

$output = array_combine($output, $output);

更新 2:我总是忘记,其实还有一个操作符(加粗是因为这个才是你真正需要的! :D)

$output = $array1 + $array2;

这些都可以在以下链接中找到:

http://php.net/manual/zh/function.array-merge.php

5
尽管引用了数字,但它们并不是字符串键,因此索引不会被保留。例如:https://ideone.com/I2NFT - Brendan Bullen
1
其实...一开始我想谈论“一个bug”,但是后来我发现,说明书只讲了“数字键”,而没有提到“整数键”。感觉有点混淆。 - KingCrunch
4
所以 $array1 + $array2 是一个简短高效的解决方案,而不用使用 array_merge() - array_combine() 的组合。 - Awan
显然是这样的。我以前从未意识到array_merge()在使用数字字符串键时的行为,一开始我期望+array_merge()的行为几乎相同,但现在看来,我学到了一些东西 :) - KingCrunch
6
警告!对于非关联数组或具有相同键的数组,$a + $b 不等于 array_merge($a, $b) - jmarceli
为了获得最佳性能,请勿使用 array_merge(),而是使用 $output = $array1 + $array2;。请参见 https://gist.github.com/Ocramius/8399625 和 https://dev59.com/8H_aa4cB1Zd3GeqPziu3#23348715。 - Avatar

37

您应该考虑到$array1 + $array2 != $array2 + $array1

$array1 = array(
'11' => 'x1',
'22' => 'x1' 
);  

$array2 = array(
'22' => 'x2',
'33' => 'x2' 
);

使用 $array1 + $array2

$array1 + $array2 = array(
'11' => 'x1',
'22' => 'x1',
'33' => 'x2'
);

并且用 $array2 + $array1

$array2 + $array1 = array(  
'11' => 'x1',  
'22' => 'x2',  
'33' => 'x2'  
);

31

这个可以正常工作:

$output = $array1 + $array2;

19
我不建议这样做,因为它的行为非常不符合直觉,例如 [1,2,3] + [4,5,6] == [1,2,3] - jchook
@jchook,那你有什么建议呢? - Michas
这正是我需要的,谢谢。原因在于:http_build_query(array_merge($array1, $array2)) 对我不起作用,而http_build_query($array1 + $array2)却可以。 - Barry

10

使用php7.4的新方法是扩展操作符[...]

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
var_dump($fruits);

扩展操作符应该比array_merge更具有性能优势。

扩展操作符的一个显着优点是它支持任何可遍历的对象,而array_merge函数仅支持数组。


当然,对于这个任务,您应该已经使用两个数字键关联数组测试了这种技术,并发现这种方法无法提供所需的行为。3v4l.org/KEQub 这个不适当/不正确的答案已经发布在错误的页面上,并且得分会误导研究人员。 - mickmackusa
我认为扩展运算符不允许使用字符串键进行解构(至少在 PHP 7.4 中是如此)。 - mwm

4
为此,您可以循环遍历一个并将其附加到另一个:
<?php

$test1 = array( 
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44'
);

$test2 = array( 
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);


function combineWithKeys($array1, $array2)
{
    foreach($array1 as $key=>$value) $array2[$key] = $value;
    asort($array2);
    return $array2;
} 

print_r(combineWithKeys($test1, $test2));

?>

更新:KingCrunch提出了最佳解决方案print_r($array1+$array2);


1

这个有效:

$a = array(1 => 1, 2 => 2, 3 => 3);
$b = array(4 => 4, 5 => 5, 6 => 6);
$c = $a + $b;
print_r($c);

1

警告!$array1 + $array2 会覆盖键名,因此我建议(针对多维数组)使用array_unique()函数。

array_unique(array_merge($a, $b), SORT_REGULAR);

注意:

5.2.10+sort_flags的默认值更改回SORT_STRING。

5.2.9 默认值为SORT_REGULAR。

5.2.8- 默认值为SORT_STRING。

完美地工作。希望能帮到您。


1
array_merge()虽然不保留键名,但创建的数组是从0开始索引的。 - HPierce
1
@HPierce 嗯,在多维数组加法的情况下,使用 + 会丢失一些信息。看一下:PHPFiddle,$b [0] 将会丢失... - Norman Edance

1
如果您使用的是 PHP 7.4 或更高版本,则可以使用扩展运算符...,如下面来自 PHP 文档的示例所示:
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3]

function getArr() {
  return ['a', 'b'];
}
$arr6 = [...getArr(), 'c']; //['a', 'b', 'c']

$arr7 = [...new ArrayIterator(['a', 'b', 'c'])]; //['a', 'b', 'c']

function arrGen() {
    for($i = 11; $i < 15; $i++) {
        yield $i;
    }
}
$arr8 = [...arrGen()]; //[11, 12, 13, 14]

它的工作方式类似于 JavaScript ES6。
更多信息请参见https://wiki.php.net/rfc/spread_operator_for_array

1
这与问题无关。OP使用数组的字符串键(这与spread运算符不兼容),OP想保留键(spread运算符会丢弃键)。此外,OP不希望出现重复项。 - martti
哦,我明白你的观点了。没错,你说得对。你能提供一些代码来帮助我们改进我的答案以便其他人使用吗?非常感谢你花时间指出我的答案的缺点。 - Student of Science
1
我认为展开运算符不是这里的正确选择。相反,使用给定的答案 $array1 + $array2 - martti
我之前不知道这个!我的意思是,我不知道我们可以用 $ouput = $array1 + $array2 这种方式。现在我学到了新东西!谢谢! - Student of Science
本页面上使用spread operator实现方法的任何答案都是不合适/不正确的,应该发布在Stack Overflow的另一页上。此页面非常明确地要求合并两个数组,这些数组具有必须保留在结果中的数值关联键。 - mickmackusa

0

这在@jchook的评论中略有探讨,但值得强调的是,+并不像人们期望的那样一致。当你处理相同的键时,结果与array_merge不同。

$a1 = array(
    'hello',
    'world',
);

$a2 = array(
    'foo',
    'baz',
);

// Will NOT work - only outputs $a1
print'<pre>';print_r($a1 + $a2);print'</pre>';

$a1 = array(
    'a' => 'hello',
    'b' => 'world',
);

$a2 = array(
    'c' => 'foo',
    'd' => 'baz',
);

// Will work (however were a and b c and d - would equally fail
print'<pre>';print_r($a1 + $a2);print'</pre>';

$a1 = array(
    1=> 'hello',
    2=> 'world',
);

$a2 = array(
    3=>'foo',
    4=>'baz',
);

// Will work
print'<pre>';print_r($a1 + $a2);print'</pre>';

如何使用“+”(数组并集运算符)合并两个数组? - mickmackusa

0

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