PHP数组按值删除(不是键)

Ada*_*ick 827 php arrays

我有一个PHP数组如下:

$messages = [312, 401, 1599, 3, ...];
Run Code Online (Sandbox Code Playgroud)

我想删除包含值的元素$del_val(例如$del_val=401),但我不知道它的键.这可能会有所帮助:每个值只能存在一次.

我正在寻找最简单的功能来执行此任务.

Boj*_*les 1468

使用array_search()unset,尝试以下方法:

if (($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
}
Run Code Online (Sandbox Code Playgroud)

array_search()返回它找到的元素的键,可以用来从原始数组中删除该元素unset().它将FALSE在失败时返回,但是它可以在成功时返回false-y值(0例如,您的密钥可能是),这就是使用严格比较运算符的原因!==.

if()语句将检查是否array_search()返回值,并且只会执行操作.

  • 尽管这是有效的,但您应该避免在这样的语句中赋值.它只会让你陷入困境. (21认同)
  • 如果`$ key`是'0`怎么办? (17认同)
  • 如果您要搜索的值具有"0"键或任何其他假值,则不会取消设置该值,并且您的代码将无效.你应该测试`$ key === false`.(编辑 - 你明白了) (16认同)
  • $ messages = array_diff($ messages,array($ del_val))也能工作吗?性能会更好吗? (14认同)
  • @Adam为什么不试试呢?我的感觉是`array_diff()`会比较慢,因为它比较了两个数组,而不是简单地搜索_one_,就像`array_search()`一样. (9认同)
  • 请注意,这不会重置数组键. (4认同)
  • 刚尝试了一个有五个0值的数组,上面的代码只删除了第一个0元素(索引= 0),而其他元素的索引为1,2,3和4. (3认同)
  • @adam正是@evan所说的.如果$ del_val的`key = 0`,你不会取消它.而且,维持这样的任务可能非常困难. (2认同)
  • 如果您需要对键重新排序,请将 `unset` 更改为 `array_splice`。`array_splice($messages, $key, 1);` (2认同)
  • 我认为这个shuold可以在while循环中完成,因为该值可以多次出现. (2认同)

Rok*_*alj 616

好吧,从数组中删除一个元素基本上只是设置一个元素的差异.

array_diff( [312, 401, 15, 401, 3], [401] ) // removing 401 returns [312, 15, 3]
Run Code Online (Sandbox Code Playgroud)

它很好地概括,如果你愿意,你可以同时删除任意数量的元素.

免责声明:请注意,我的解决方案会生成一个新的数组副本,同时保持旧数据的完整性与已接受的答案相反.由于这个原因,它可能会有点慢.

  • 这仅适用于可以转换为字符串的对象 (31认同)
  • 值得注意的是,由于某种原因,`array_diff`使用`(string)$ elem1 ===(string)$ elem2`作为它的相等条件,而不是你想象中的`$ elem1 === $ elem2`.@ nischayn22指出的问题就是这个问题的结果.如果你想要一些东西用作实用函数,它可以用于任意元素的数组(可能是对象),那么Bojangle的答案可能更好. (22认同)
  • 当然,我认为PHP 5.4现在占据了大多数人的意见.谢谢你的评论. (8认同)
  • 我似乎得到了一个'Parse Error'来说'[$ element]`,我用'array($ element)`来代替.没什么大不了的,但只是想让有类似问题的人知道他们并不孤单 (7认同)
  • 另请注意,此方法在内部对"array_diff()"的每个参数执行排序,从而将运行时从O(n)推到O(n lg n). (4认同)

Ja͢*_*͢ck 106

一个有趣的方法是使用array_keys():

foreach (array_keys($messages, 401, true) as $key) {
    unset($messages[$key]);
}
Run Code Online (Sandbox Code Playgroud)

array_keys()函数需要两个附加参数来仅返回特定值的键以及是否需要严格检查(即使用===进行比较).

这也可以删除具有相同值的多个数组项(例如[1, 2, 3, 3, 4]).

  • @blasteralfredΨ线性搜索是O(n); 我不确定你为什么认为这是一个问题. (3认同)
  • 这对于可能不包含所有唯一值的数组来说是最好的。 (3认同)
  • @Rodniko在这种情况下你也需要`array_values()`; 其余的键仍然是相同的顺序,所以从技术上讲,它不是"未排序" (3认同)

adl*_*son 51

如果您确定您的数组只包含一个具有该值的元素,那么您可以这样做

$key = array_search($del_val, $array);
if (false !== $key) {
    unset($array[$key]);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您的值可能在阵列中出现多次,则可以执行此操作

$array = array_filter($array, function($e) use ($del_val) {
    return ($e !== $del_val);
});
Run Code Online (Sandbox Code Playgroud)

注意:第二个选项仅适用于带有闭包的 PHP5.3 +


Rma*_*nnn 39

$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);
Run Code Online (Sandbox Code Playgroud)

  • 仅当您的数组不包含您尝试删除的值之外的重复值时,此方法才有效. (10认同)
  • @jberculo,有时正是您所需要的,在某些情况下,它使我免于在其上做一个唯一的数组 (2认同)
  • 显然,与选定的解决方案相比,这是最快的,我做了小基准测试. (2认同)

the*_*ine 27

看看下面的代码:

$arr = array('nice_item', 'remove_me', 'another_liked_item', 'remove_me_also');
Run Code Online (Sandbox Code Playgroud)

你可以做:

$arr = array_diff($arr, array('remove_me', 'remove_me_also'));
Run Code Online (Sandbox Code Playgroud)

这会得到你这个数组:

array('nice_item', 'another_liked_item')
Run Code Online (Sandbox Code Playgroud)

  • 这有什么不同于[这个答案](http://stackoverflow.com/a/10455129/870729)? (4认同)

Abd*_*rai 21

最好的方法是 array_splice

array_splice($array, array_search(58, $array ), 1);
Run Code Online (Sandbox Code Playgroud)

最佳理由来自http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/

  • 这不适用于关键数组和键中有间隙的数组,例如`[1,2,4 => 3]`. (4认同)
  • 它不会.考虑我上面评论的数组; 在我使用你的代码删除值`3`之后,数组将是`[1,2,3]`; 换句话说,该值未被删除.要清楚,我并不是说它在所有场景中都失败了,只是这个. (4认同)

Sye*_*man 19

By the following code, the repetitive values will be removed from the $messages.

$messages = array_diff($messages, array(401));

  • 上投了反对票.它已经是其他答案中的一部分了,但你说它最简单,就像你一样.答案就是"array_diff" (3认同)

小智 18

或者简单地说,手动方式:

foreach ($array as $key => $value){
    if ($value == $target_value) {
        unset($array[$key]);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是最安全的,因为您可以完全控制阵列


Dav*_*Lin 15

如果您有> php5.3,则有一行代码:

$array = array_filter($array, function ($i) use ($value) { return $i !== $value; }); 
Run Code Online (Sandbox Code Playgroud)

  • 如果你称之为"一行代码",你也可以在一行上编写整个代码库. (3认同)

Roy*_*Roy 14

在 PHP 7.4 中使用箭头函数:

$messages = array_filter($messages, fn ($m) => $m != $del_val);
Run Code Online (Sandbox Code Playgroud)

为了保持它是一个非关联数组,用array_values()以下内容包装它:

$messages = array_values(array_filter($messages, fn ($m) => $m != $del_val));
Run Code Online (Sandbox Code Playgroud)


ttt*_*ony 13

function array_remove_by_value($array, $value)
{
    return array_values(array_diff($array, array($value)));
}

$array = array(312, 401, 1599, 3);

$newarray = array_remove_by_value($array, 401);

print_r($newarray);
Run Code Online (Sandbox Code Playgroud)

产量

Array ( [0] => 312 [1] => 1599 [2] => 3 )

  • 这个解决方案重组了索引,做得不错. (2认同)
  • 我不确定这是否更快,因为此解决方案涉及多个函数调用。 (2认同)
  • 仅代码答案在 Stack Overflow 上的价值很低。每个答案都应该包括对其工作原理的解释,或者为什么您认为与其他技术相比这是一个好建议。 (2认同)

Kou*_*Das 13

PHP 7.4 或更高版本

function delArrValues(array $arr, array $remove) {
    return array_filter($arr, fn($e) => !in_array($e, $remove));
};
Run Code Online (Sandbox Code Playgroud)

所以,如果你有数组

$messages = [312, 401, 1599, 3];
Run Code Online (Sandbox Code Playgroud)

并且您想3, 312从 $messages 数组中删除两者,您可以这样做

delArrValues($messages, [3, 312])
Run Code Online (Sandbox Code Playgroud)

它会返回

[401, 1599]
Run Code Online (Sandbox Code Playgroud)

最好的部分是您可以轻松过滤多个值,即使同一值多次出现。


Qur*_*shi 11

你可以做:

unset($messages[array_flip($messages)['401']]);
Run Code Online (Sandbox Code Playgroud)

说明:401翻转数组后删除具有该键的元素.

  • 不确定这是否正确,如果有多个值为 `401` 的元素怎么办? (3认同)
  • @saadlulu $messages 数组不会被翻转,因为 array_flip() 不会影响原始数组,因此应用前一行后的结果数组将是相同的,除了不需要的结果将被删除。 (2认同)

Raj*_*iya 7

要删除多个值,请尝试此操作

while (($key = array_search($del_val, $messages)) !== false) 
{
    unset($messages[$key]);
}
Run Code Online (Sandbox Code Playgroud)

  • 这比循环一次输入的效率要低(并且有多种工具可以执行此操作)。想象一下,您正在迭代一个包含 10 个元素的索引数组,并且想要删除索引 4 和 8 处的元素。这将从 0 迭代到 4,然后取消设置元素 [4],然后它将迭代 0 到 8,然后取消设置元素 [ 8]。看看这种技术如何不必要地多次检查 [0]、[1]、[2]、[3]。我永远不会出于任何原因使用这种技术,我建议所有研究人员从这个答案中广泛借鉴。(这就是我做DV的原因) (3认同)

Ism*_*ael 7

如果您不知道其密钥,则意味着它并不重要。

您可以将值作为键,这意味着它会立即找到该值。比一遍又一遍地在所有元素中使用搜索要好。

$messages=array();   
$messages[312] = 312;    
$messages[401] = 401;   
$messages[1599] = 1599;   
$messages[3] = 3;    

unset($messages[3]); // no search needed
Run Code Online (Sandbox Code Playgroud)


Sai*_*akR 6

接受的答案将数组转换为关联数组,因此,如果您想将其保留为与接受的答案的非关联数组,您可能也必须使用array_values

if(($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
    $arr = array_values($messages);
}
Run Code Online (Sandbox Code Playgroud)

参考在这里


Joh*_*dis 5

借用下划线JS _.reject的逻辑并创建了两个函数(人们更喜欢函数!!)

array_reject_value:这个函数只是拒绝指定的值(也适用于PHP4,5,7)

function array_reject_value(array &$arrayToFilter, $deleteValue) {
    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if ($value !== $deleteValue) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}
Run Code Online (Sandbox Code Playgroud)

array_reject:这个函数只是拒绝可调用的方法(适用于PHP> = 5.3)

function array_reject(array &$arrayToFilter, callable $rejectCallback) {

    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if (!$rejectCallback($value, $key)) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}
Run Code Online (Sandbox Code Playgroud)

所以在我们当前的例子中,我们可以使用上面的函数如下:

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject_value($messages, 401);
Run Code Online (Sandbox Code Playgroud)

甚至更好:(因为这给了我们一个更好的语法来使用像array_filter一样)

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject($messages, function ($value) {
    return $value === 401;
});
Run Code Online (Sandbox Code Playgroud)

以上内容可以用于更复杂的内容,比如我们想要删除大于或等于401的所有值,我们可以简单地执行此操作:

$messages = [312, 401, 1599, 3, 6];
$greaterOrEqualThan = 401;
$messages = array_reject($messages, function ($value) use $greaterOrEqualThan {
    return $value >= $greaterOrEqualThan;
});
Run Code Online (Sandbox Code Playgroud)

  • 这不是重新发明过滤器吗?http://php.net/manual/en/function.array-filter.php (3认同)