如果数组中没有该元素,则将其添加到数组中。

88

如何将元素添加到数组中,只有当它们不在数组中时才添加? 我有以下代码:

$a=array();
// organize the array
foreach($array as $k=>$v){
    foreach($v as $key=>$value){
        if($key=='key'){
        $a[]=$value;
        }
    }
}

print_r($a);

// 输出结果

Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 1
[4] => 2
[5] => 3
[6] => 4
[7] => 5
[8] => 6

)

相反,我希望$a由唯一的值组成。(我知道可以使用array_unique获得所需结果,但我只想知道)


对于那些寻找 Laravel 解决方案的人来说,Arr::wrap() 就是答案,详见文档 - peter.babic
14个回答

186

你应该使用PHP函数in_array(参见http://php.net/manual/en/function.in-array.php)。

if (!in_array($value, $array))
{
    $array[] = $value; 
}

根据文档,in_array 的作用如下:

如果数组中包含指定元素,则返回TRUE,否则返回FALSE


4
这绝对是做这件事情最简单的方法。 - tim.baker

71
你需要对每个值进行检查,看看是否与in_array匹配。
$a=array();
// organize the array by cusip
foreach($array as $k=>$v){
    foreach($v as $key=>$value){
        if(!in_array($value, $a)){
        $a[]=$value;
        }
    }
}

4
随着输入数据量的增加,“in_array()”函数的性能将变得越来越糟糕。 - mickmackusa

30

因为您似乎只有标量值,而PHP的数组实际上是一个哈希映射,因此您可以使用值作为键来避免重复,并将$k键与它们关联以便能够获取原始值:

$keys = array();
foreach ($array as $k => $v){
    if (isset($v['key'])) {
        $keys[$value] = $k;
    }
}

然后您只需要迭代它以获取原始值:

$unique = array();
foreach ($keys as $key) {
    $unique[] = $array[$key]['key'];
}

这可能不是最明显和最全面的方法,但它非常高效,因为它是以 O(n) 的时间复杂度运行的。

像其他人建议的那样使用 in_array 可能更直观。但你最终会得到一个以 O(n2) 的时间复杂度运行的算法(in_array 是以 O(n) 运行的),这是不可行的。即使将所有值推入数组并在其上使用array_unique也比使用in_array更好(array_unique 以 O(n·log n) 对值进行排序,然后删除连续的重复项)。


这是我大多数情况下偏爱的解决方案。在 PHP 中,数组键很强大。 - cweiske
@xmedeko 提出了一项建议编辑,认为成本是 O(n logn) 而不是 O(n),因为涉及到“PHP哈希”的成本,你们能否在这里达成一致呢? :-) - Kos
依我看,array_unique 可以保留原始数值顺序,而您的解决方案则不能。 - xmedeko

17
if (!in_array(...))  
  array_push(..)

10

容易编写,但不是最有效的:

$array = array_unique(array_merge($array, $array_to_append));

这个可能更快:

$array = array_merge($array, array_diff($array_to_append, $array));

很棒的解决方案,谢谢。 - Malus Jan
1
根据我的 IDE(PHPStorm,因为我没有进行性能比较),第一个更快。使用array_merge + array_diff时,PHPStorm 给出了“在循环中使用资源密集型操作”的警告。 - Catar4

6
if (!in_array($value, $a))
  $a[]=$value;

4

尝试将其作为键添加而非值:

添加条目

function addEntry($entry) {
    $this->entries[$entry] = true;
}

获取所有条目
function getEntries() {
    return array_keys($this->enties);
}

这是Java如何实现HashSets的方式(使用嵌入式HashMap和一个值,我认为包含一个静态的new Object())。 - Erk

4

如果你在代码中使用简写(而不是像某些编程标准建议的那样编写显式的if块),你可以使用这个一行代码进一步简化Marius Schulz的答案

in_array ($value, $array) || $array [] = $value;

3

由于有很多方法可以实现所需的结果,许多人提供了!in_array()作为答案,而且OP已经提到使用了array_unique,我想提供一些替代方案。

使用array_diff(php >= 4.0.1 || 5)可以过滤掉仅存在于新数组中的值。或者,您还可以使用array_diff_assoc比较键和值。http://php.net/manual/en/function.array-diff.php

$currentValues = array(1, 2);
$newValues = array(1, 3, 1, 4, 2);
var_dump(array_diff($newValues, $currentValues));

结果:

Array
(
    [1] => 3
    [3] => 4
)

http://ideone.com/SWO3D1

另一种方法是使用array_flip将值分配为键,并使用isset进行比较,这比在大数据集上使用in_array要快得多。同样,这会过滤掉当前值中不存在的新值。
$currentValues = [1, 2];
$newValues = [1, 3, 1, 4, 2];
$a = array();
$checkValues = array_flip($currentValues);
foreach ($newValues as $v) {
    if (!isset($checkValues[$v])) {
        $a[] = $v;
    }
}

结果:

Array
(
    [0] => 3
    [1] => 4
)

http://ideone.com/cyRyzN

使用任一方法,您都可以使用array_merge将唯一的新值附加到当前值。

  1. http://ideone.com/JCakmR
  2. http://ideone.com/bwTz2u

结果:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
)

3

如果您不关心键的顺序,可以按照以下方式操作:

$array = YOUR_ARRAY
$unique = array();
foreach ($array as $a) {
    $unique[$a] = $a;
}

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