在PHP中从数组中删除元素

有没有一种简单的方法可以使用PHP从数组中删除元素,使得foreach ($array)不再包含该元素?

我以为将其设置为null就可以了,但显然它不起作用。

3477604 次浏览

删除数组元素有不同的方法,其中一些方法对某些特定任务比其他方法更有用。

删除单个数组元素

如果您只想删除一个数组元素,您可以使用#0#1

如果您知道值但不知道删除元素的键,您可以使用#0来获取键。这仅适用于元素不发生多次的情况,因为\array_search仅返回第一次命中。

unset()

请注意,当您使用unset()时,数组键不会改变。如果您想重新索引键,您可以在unset()之后使用#1,这将把所有键转换为从0开始的数字枚举键。

代码:

$array = [0 => "a", 1 => "b", 2 => "c"];unset($array[1]);// ↑ Key which you want to delete

输出:

[[0] => a[2] => c]

#0方法

如果您使用\array_splice(),键将自动重新索引,但关联键不会改变-与\array_values()相反,它将所有键转换为数字键。

\array_splice()需要偏移,而不是关键作为第二个参数。

代码:

$array = [0 => "a", 1 => "b", 2 => "c"];\array_splice($array, 1, 1);// ↑ Offset which you want to delete

输出:

[[0] => a[1] => c]

array_splice(),与unset()相同,通过引用获取数组。您不将这些函数的返回值分配回数组。

删除多个数组元素

如果您想删除多个数组元素并且不想多次调用unset()\array_splice(),您可以使用函数\array_diff()\array_diff_key(),具体取决于您是否知道要删除的元素的值或键。

#0方法

如果您知道要删除的数组元素的值,那么您可以使用\array_diff()。与之前的unset()一样,它不会更改数组的键。

代码:

$array = [0 => "a", 1 => "b", 2 => "c", 3 => "c"];$array = \array_diff($array, ["a", "c"]);// └────────┘// Array values which you want to delete

输出:

[[1] => b]

#0方法

如果您知道要删除的元素的键,那么您想使用\array_diff_key()。您必须确保将键作为第二个参数中的键而不是值传递。键不会重新索引。

代码:

$array = [0 => "a", 1 => "b", 2 => "c"];$array = \array_diff_key($array, [0 => "xy", "2" => "xy"]);// ↑           ↑// Array keys which you want to delete

输出:

[[1] => b]

如果您想使用unset()\array_splice()删除具有相同值的多个元素,您可以使用#2获取特定值的所有键,然后删除所有元素。

#0方法

如果您想删除数组中具有特定值的所有元素,您可以使用\array_filter()

代码:

$array = [0 => "a", 1 => "b", 2 => "c"];$array = \array_filter($array, static function ($element) {return $element !== "b";//                   ↑// Array value which you want to delete});

输出:

[[0] => a[1] => c]
unset($array[$index]);

应该注意的是,#0将保持索引不变,这是您在使用字符串索引(数组作为哈希表)时所期望的,但在处理整数索引数组时可能会非常令人惊讶:

$array = array(0, 1, 2, 3);unset($array[2]);var_dump($array);/* array(3) {[0]=>int(0)[1]=>int(1)[3]=>int(3)} */
$array = array(0, 1, 2, 3);array_splice($array, 2, 1);var_dump($array);/* array(3) {[0]=>int(0)[1]=>int(1)[2]=>int(3)} */

因此,如果您想规范化整数键,可以使用#0。另一种选择是在#2之后使用#1

$array = array(0, 1, 2, 3);
unset($array[2]);$array = array_values($array);var_dump($array);/* array(3) {[0]=>int(0)[1]=>int(1)[2]=>int(3)} */

此外,对于命名元素:

unset($array["elementName"]);
  // Our initial array$arr = array("blue", "green", "red", "yellow", "green", "orange", "yellow", "indigo", "red");print_r($arr);
// Remove the elements who's values are yellow or red$arr = array_diff($arr, array("yellow", "red"));print_r($arr);

这是上面代码的输出:

Array([0] => blue[1] => green[2] => red[3] => yellow[4] => green[5] => orange[6] => yellow[7] => indigo[8] => red)
Array([0] => blue[1] => green[4] => green[5] => orange[7] => indigo)

现在,array_values()会很好地重新索引一个数字数组,但它会从数组中删除所有键字符串并用数字替换它们。如果你需要保留键名(字符串),或者如果所有键都是数字,则重新索引数组,请使用array_merge():

$arr = array_merge(array_diff($arr, array("yellow", "red")));print_r($arr);

产出

Array([0] => blue[1] => green[2] => green[3] => orange[4] => indigo)
$key = array_search($needle, $array);if ($key !== false) {unset($array[$key]);}

如果你有一个数字索引数组,其中所有值都是唯一的(或者它们不是唯一的,但你希望删除特定值的所有实例),你可以简单地使用array_diff()来删除匹配元素,如下所示:

$my_array = array_diff($my_array, array('Value_to_remove'));

例如:

$my_array = array('Andy', 'Bertha', 'Charles', 'Diana');echo sizeof($my_array) . "\n";$my_array = array_diff($my_array, array('Charles'));echo sizeof($my_array);

这将显示以下内容:

43

在此示例中,具有值“Charles”的元素被删除,因为可以通过sizeof()调用进行验证,该调用报告初始数组的大小为4,删除后为3。

使用以下代码:

$arr = array('orange', 'banana', 'apple', 'raspberry');$result = array_pop($arr);print_r($result);
<?php$stack = ["fruit1", "fruit2", "fruit3", "fruit4"];$fruit = array_shift($stack);print_r($stack);
echo $fruit;?>

输出:

[[0] => fruit2[1] => fruit3[2] => fruit4]
fruit1

unset()销毁指定的变量。

函数内部unset()的行为可以根据您尝试销毁的变量类型而有所不同。

如果函数内部的全局变量为unset(),则仅销毁局部变量。调用环境中的变量将保留与调用unset()之前相同的值。

<?phpfunction destroy_foo(){global $foo;unset($foo);}
$foo = 'bar';destroy_foo();echo $foo;?>

上面代码的答案将是酒吧

unset()函数内部的全局变量:

<?phpfunction foo(){unset($GLOBALS['bar']);}
$bar = "something";foo();?>

我只想说我有一个具有可变属性的特定对象(它基本上是映射一个表,我正在更改表中的列,因此对象中反映表的属性也会有所不同):

class obj {protected $fields = array('field1','field2');protected $field1 = array();protected $field2 = array();protected loadfields(){}// This will load the $field1 and $field2 with rows of data for the column they describeprotected function clearFields($num){foreach($fields as $field) {unset($this->$field[$num]);// This did not work the line below workedunset($this->{$field}[$num]); // You have to resolve $field first using {}}}}

$fields的全部目的只是,所以当它们被更改时,我不必在代码中到处寻找,我只需要查看类的开头并更改属性列表和$字段数组内容以反映新属性。

假设您有以下数组:

Array([user_id] => 193[storage] => 5)

要删除storage,请执行:

unset($attributes['storage']);$attributes = array_filter($attributes);

你会得到:

Array([user_id] => 193)

销毁数组的单个元素

unset()

$array1 = array('A', 'B', 'C', 'D', 'E');unset($array1[2]); // Delete known index(2) value from arrayvar_dump($array1);

输出将是:

array(4) {[0]=>string(1) "A"[1]=>string(1) "B"[3]=>string(1) "D"[4]=>string(1) "E"}

如果您需要重新索引数组:

$array1 = array_values($array1);var_dump($array1);

然后输出将是:

array(4) {[0]=>string(1) "A"[1]=>string(1) "B"[2]=>string(1) "D"[3]=>string(1) "E"}

从数组末尾弹出元素-返回删除元素的值

mixed array_pop(array &$array)

$stack = array("orange", "banana", "apple", "raspberry");$last_fruit = array_pop($stack);print_r($stack);print_r('Last Fruit:'.$last_fruit); // Last element of the array

输出将是

Array([0] => orange[1] => banana[2] => apple)Last Fruit: raspberry

从数组中删除第一个元素(红色),-返回删除元素的值

mixed array_shift ( array &$array )

$color = array("a" => "red", "b" => "green" , "c" => "blue");$first_color = array_shift($color);print_r ($color);print_r ('First Color: '.$first_color);

输出将是:

Array([b] => green[c] => blue)First Color: red

遵循默认函数:

  • PHP:未设置

unset()销毁指定的变量。有关更多信息,您可以参考PHP取消设置

$Array = array("test1", "test2", "test3", "test3");
unset($Array[2]);
  • PHP:array_pop

array_pop()函数删除数组的最后一个元素。有关更多信息,您可以参考PHParray_pop

$Array = array("test1", "test2", "test3", "test3");
array_pop($Array);
  • PHP:array_splice

array_splice()函数从数组中删除选定的元素并将其替换为新元素。有关更多信息,您可以参考PHParray_splice

$Array = array("test1", "test2", "test3", "test3");
array_splice($Array,1,2);
  • PHP:array_shift

array_shift()函数从数组中删除第一个元素。有关更多信息,您可以参考PHParray_shift

$Array = array("test1", "test2", "test3", "test3");
array_shift($Array);

如果您必须删除数组中的多个值,并且该数组中的条目是对象或结构化数据,那么#0是您最好的选择。那些从回调函数返回true的条目将被保留。

$array = [['x'=>1,'y'=>2,'z'=>3],['x'=>2,'y'=>4,'z'=>6],['x'=>3,'y'=>6,'z'=>9]];
$results = array_filter($array, function($value) {return $value['x'] > 2;}); //=> [['x'=>3,'y'=>6,z=>'9']]

关联数组

对于关联数组,使用#0

$arr = array('a' => 1, 'b' => 2, 'c' => 3);unset($arr['b']);
// RESULT: array('a' => 1, 'c' => 3)

数字数组

对于数字数组,使用#0

$arr = array(1, 2, 3);array_splice($arr, 1, 1);
// RESULT: array(0 => 1, 1 => 3)

说明

对数字数组使用#0不会产生错误,但会弄乱您的索引:

$arr = array(1, 2, 3);unset($arr[1]);
// RESULT: array(0 => 1, 2 => 3)
// Remove by valuefunction removeFromArr($arr, $val){unset($arr[array_search($val, $arr)]);return array_values($arr);}

如果您需要从关联数组中删除多个元素,您可以使用array_diff_key()(此处与array_flip()一起使用):

$my_array = array("key1" => "value 1","key2" => "value 2","key3" => "value 3","key4" => "value 4","key5" => "value 5",);
$to_remove = array("key2", "key4");
$result = array_diff_key($my_array, array_flip($to_remove));
print_r($result);

输出:

Array ( [key1] => value 1 [key3] => value 3 [key5] => value 5 )
<?php// If you want to remove a particular array element use this method$my_array = array("key1"=>"value 1", "key2"=>"value 2", "key3"=>"value 3");
print_r($my_array);if (array_key_exists("key1", $my_array)) {unset($my_array['key1']);print_r($my_array);}else {echo "Key does not exist";}?>
<?php//To remove first array element$my_array = array("key1"=>"value 1", "key2"=>"value 2", "key3"=>"value 3");print_r($my_array);$new_array = array_slice($my_array, 1);print_r($new_array);?>

<?phpecho "<br/>    ";// To remove first array element to length// starts from first and remove two element$my_array = array("key1"=>"value 1", "key2"=>"value 2", "key3"=>"value 3");print_r($my_array);$new_array = array_slice($my_array, 1, 2);print_r($new_array);?>

产出

 Array ( [key1] => value 1 [key2] => value 2 [key3] =>value 3 ) Array (    [key2] => value 2 [key3] => value 3 )Array ( [key1] => value 1 [key2] => value 2 [key3] => value 3 )Array ( [key2] => value 2 [key3] => value 3 )Array ( [key1] => value 1 [key2] => value 2 [key3] => value 3 )Array ( [key2] => value 2 [key3] => value 3 )

根据键删除数组元素:

使用unset函数,如下所示:

$a = array('salam','10',1);
unset($a[1]);
print_r($a);
/*
Output:
Array([0] => salam[2] => 1)
*/

根据值删除数组元素:

使用array_search函数获取元素键,并使用上述方式删除数组元素,如下所示:

$a = array('salam','10',1);
$key = array_search(10, $a);
if ($key !== false) {unset($a[$key]);}
print_r($a);
/*
Output:
Array([0] => salam[2] => 1)
*/

unset()数组中的多个碎片元素

虽然这里已经多次提到unset(),但还没有提到unset()接受多个变量,这使得在一次操作中从数组中删除多个不连续的元素变得容易:

// Delete multiple, noncontiguous elements from an array$array = [ 'foo', 'bar', 'baz', 'quz' ];unset( $array[2], $array[3] );print_r($array);// Output: [ 'foo', 'bar' ]

动态地unset()

unset()不接受要删除的键数组,因此下面的代码会失败(不过动态使用unset()会稍微容易一些)。

$array = range(0,5);$remove = [1,2];$array = unset( $remove ); // FAILS: "unexpected 'unset'"print_r($array);

相反,unset()可以在Foreach循环中动态使用:

$array = range(0,5);$remove = [1,2];foreach ($remove as $k=>$v) {unset($array[$v]);}print_r($array);// Output: [ 0, 3, 4, 5 ]

通过复制数组来删除数组键

还有另一种做法尚未提及。有时,摆脱某些数组键的最简单方法是简单地将$array1复制到$array2中。

$array1 = range(1,10);foreach ($array1 as $v) {// Remove all even integers from the arrayif( $v % 2 ) {$array2[] = $v;}}print_r($array2);// Output: [ 1, 3, 5, 7, 9 ];

显然,同样的做法也适用于文本字符串:

$array1 = [ 'foo', '_bar', 'baz' ];foreach ($array1 as $v) {// Remove all strings beginning with underscoreif( strpos($v,'_')===false ) {$array2[] = $v;}}print_r($array2);// Output: [ 'foo', 'baz' ]

解决方案:

  1. 要删除一个元素,请使用unset()
unset($array[3]);unset($array['foo']);
  1. 要删除多个不连续的元素,还可以使用unset()
unset($array[3], $array[5]);unset($array['foo'], $array['bar']);
  1. 要删除多个连续元素,请使用array_splice()
array_splice($array, $offset, $length);

进一步解释:

使用这些函数会从PHP中删除对这些元素的所有引用。如果您想在数组中保留一个键,但使用空值,请将空字符串分配给元素:

$array[3] = $array['foo'] = '';

除了语法之外,使用unset()和将“”赋值给元素之间还有一个逻辑上的区别。第一个说This doesn't exist anymore,,第二个说This still exists, but its value is the empty string.

如果您正在处理数字,分配0可能是更好的选择。因此,如果一家公司停止生产XL1000型链轮,它将更新其库存:

unset($products['XL1000']);

但是,如果它暂时用完了XL1000链轮,但计划在本周晚些时候从工厂接收新的货物,这是更好的:

$products['XL1000'] = 0;

如果您unset()一个元素,PHP会调整数组以使循环仍然正常工作。它不会压缩数组以填补缺失的漏洞。这就是我们所说的所有数组都是关联的,即使它们看起来是数字。这是一个例子:

// Create a "numeric" array$animals = array('ant', 'bee', 'cat', 'dog', 'elk', 'fox');print $animals[1];  // Prints 'bee'print $animals[2];  // Prints 'cat'count($animals);    // Returns 6
// unset()unset($animals[1]); // Removes element $animals[1] = 'bee'print $animals[1];  // Prints '' and throws an E_NOTICE errorprint $animals[2];  // Still prints 'cat'count($animals);    // Returns 5, even though $array[5] is 'fox'
// Add a new element$animals[ ] = 'gnu'; // Add a new element (not Unix)print $animals[1];  // Prints '', still emptyprint $animals[6];  // Prints 'gnu', this is where 'gnu' ended upcount($animals);    // Returns 6
// Assign ''$animals[2] = '';   // Zero out valueprint $animals[2];  // Prints ''count($animals);    // Returns 6, count does not decrease

要将数组压缩为密集填充的数字数组,请使用array_values()

$animals = array_values($animals);

或者,array_splice()自动重新索引数组以避免留下漏洞:

// Create a "numeric" array$animals = array('ant', 'bee', 'cat', 'dog', 'elk', 'fox');array_splice($animals, 2, 2);print_r($animals);Array([0] => ant[1] => bee[2] => elk[3] => fox)

如果您将数组用作队列并希望从队列中删除项目,同时仍然允许随机访问,这很有用。要安全地从数组中删除第一个或最后一个元素,请分别使用array_shift()array_pop()

有两种方法可以删除数组的第一项,保持索引的顺序,如果您不知道第一项的键名。

解决方案#1

// 1 is the index of the first object to get// NULL to get everything until the end// true to preserve keys$array = array_slice($array, 1, null, true);

解决方案#2

// Rewinds the array's internal pointer to the first element// and returns the value of the first array element.$value = reset($array);// Returns the index element of the current array position$key = key($array);unset($array[$key]);

对于此示例数据:

$array = array(10 => "a", 20 => "b", 30 => "c");

你必须得到这个结果:

array(2) {[20]=>string(1) "b"[30]=>string(1) "c"}

如果指定索引:

$arr = ['a', 'b', 'c'];$index = 0;unset($arr[$index]);  // $arr = ['b', 'c']

如果我们有值而不是索引:

$arr = ['a', 'b', 'c'];
// search the value to find index// Notice! this will only find the first occurrence of value$index = array_search('a', $arr);
if($index !== false){unset($arr[$index]);  // $arr = ['b', 'c']}

if条件是必要的因为如果没有找到indexunset()会自动删除数组的第一个元素不是我们想要的。

编辑

如果你不能假设对象在该数组中,你需要添加一个检查:

if(in_array($object,$array)) unset($array[array_search($object,$array)]);

原始答案

如果您想通过引用该对象来删除数组的特定对象,您可以执行以下操作:

unset($array[array_search($object,$array)]);

示例:

<?phpclass Foo{public $id;public $name;}
$foo1 = new Foo();$foo1->id = 1;$foo1->name = 'Name1';
$foo2 = new Foo();$foo2->id = 2;$foo2->name = 'Name2';
$foo3 = new Foo();$foo3->id = 3;$foo3->name = 'Name3';

$array = array($foo1,$foo2,$foo3);unset($array[array_search($foo2,$array)]);
echo '<pre>';var_dump($array);echo '</pre>';?>

结果:

array(2) {[0]=>object(Foo)#1 (2) {["id"]=>int(1)["name"]=>string(5) "Name1"}[2]=>object(Foo)#3 (2) {["id"]=>int(3)["name"]=>string(5) "Name3"}}

请注意,如果对象多次出现,它只会在第一次出现时被删除!

我来到这里是因为我想看看是否有比使用unset($arr[$i])更优雅的解决方案来解决这个问题。令我失望的是,这些答案要么是错误的,要么没有涵盖所有边缘情况。

这就是为什么array_diff()不起作用的原因。键在数组中是唯一的,而元素并不总是唯一的。

$arr = [1,2,2,3];
foreach($arr as $i => $n){$b = array_diff($arr,[$n]);echo "\n".json_encode($b);}

结果…

[2,2,3][1,3][1,2,2]

如果两个元素相同,它们将被删除。这也适用于array_search()和array_flip()。

我看到了很多array_slice()和array_splice()的答案,但这些函数只适用于数字数组。如果这里没有回答问题,我知道的所有答案,所以这里有一个可以工作的解决方案。

$arr = [1,2,3];
foreach($arr as $i => $n){$b = array_merge(array_slice($arr,0,$i),array_slice($arr,$i+1));echo "\n".json_encode($b);}
Results...
[2,3];[1,3];[1,2];

由于unset($arr[$i])适用于关联数组和数字数组,因此仍然无法回答问题。

此解决方案是比较键并使用将处理数字和关联数组的工具。我为此使用array_diff_uassoc()。此函数比较回调函数中的键。

$arr = [1,2,2,3];//$arr = ['a'=>'z','b'=>'y','c'=>'x','d'=>'w'];foreach($arr as $key => $n){$b = array_diff_uassoc($arr, [$key=>$n], function($a,$b) {if($a != $b){return 1;}});echo "\n".json_encode($b);}

结果

[2,2,3];[1,2,3];[1,2,2];
['b'=>'y','c'=>'x','d'=>'w'];['a'=>'z','c'=>'x','d'=>'w'];['a'=>'z','b'=>'y','d'=>'w'];['a'=>'z','b'=>'y','c'=>'x'];