如何使用PHP从数组中删除特定的键?

16

我有一个包含4个值的数组。我想删除第二个位置上的值,然后数组中其余的值向下移位。

$b = array(123,456,789,123);

移除第二个位置的键之前:

数组 ( [0] => 123 [1] => 456 [2] => 789 [3] => 123 )

我想移除一个键后,希望其余的键向下移动一位来填补缺失的空间。

数组 ( [0] => 123 [1] => 789 [2] => 123 )

我尝试使用 unset() 来删除指定的键,但它不会将剩余的键向下移动。如何在 PHP 中删除数组中的特定键?


5个回答

11

为了重新对数组进行键名的排序并使其顺序递增,您需要使用array_values($b)

下面的代码可以实现此功能:

$b = array(123,456,789,123);
unset($b[1]);
$b = array_values($b);
echo "<pre>"; print_r($b);

+1:只需添加一个检查:array_key_exists,如果您计划使其动态 :) - Nonym
没有必要为此任务调用array_key_exists()。如果您告诉php取消设置unset($b[9999999]),它将悄无声息地不做任何事情--检查没有任何好处。@Nonym - mickmackusa

10

据表示,您的输入数据是一个索引数组(在从零开始的整数键序列中没有间隙)。我将比较直接从OP的示例数据中提供所需结果的明显技术。

1. unset() 然后 array_values()

unset($b[1]);
$b = array_value($b);
  • 如果索引不存在,则可以放心使用此函数而不必检查 -- 如果缺失,不会出现错误。
  • unset() 可以接收多个参数,因此如果需要删除更多元素,则函数调用的数量保持不变。例如:unset($b[1], $b[3], $b[5]);
  • unset() 不能嵌套在 array_values() 中形成一行代码,因为 unset() 修改变量并且不返回任何值。
  • 据我所知,unset() 对于使用动态白名单/黑名单键来删除元素并不特别方便。

2. array_splice()

array_splice($b, 1, 1);
//          (input array, starting position, number of elements to remove)
  • 这个函数是无关键字的,它将基于数组中元素的位置来定位目标元素。即使缺少位置,使用它也是安全的--如果缺失,则不会出错。
  • array_splice() 可以删除单个元素或者连续的多个元素。如果你需要删除非连续的元素,你需要进行额外的函数调用。
  • array_splice() 不需要 array_values() 调用,因为“输入中的数字键不会被保留”--在某些情况下,这可能是可取的。

3. array_filter() 嵌套在 array_values()

array_values(
    array_filter(
        $b,
        function($k) {
            return $k != 1;
        },
        ARRAY_FILTER_USE_KEY
    )
)
  • 这种技术依赖于自定义函数调用和标志,告诉过滤器仅迭代键。
  • 它的性能相对较差,因为它将迭代所有元素,而不管逻辑必要性。
  • 这是我将讨论的选项中最冗长的。
  • 如果您想在自定义函数中使用白名单/黑名单的in_array()调用,则会进一步失去效率。
  • 在PHP7.4之前,将白名单/黑名单/变量传递到自定义函数范围中将需要使用use()
  • 它可以写成一行代码。
  • 即使缺少索引,也可以安全使用此方法--没有错误。

4. array_diff_key()嵌套在array_values()

array_values(
    array_diff_key(
        $b,
        [1 => '']
    )
);
  • 如果只需要删除一个元素,这种方法并不是很啰嗦,但有点杀鸡焉用牛刀。
  • array_diff_key() 在白名单/黑名单数组的键(可能具有不同数量的元素)时表现得非常出色。PHP 在处理键方面非常迅速,因此这个函数在它所设计的任务上非常高效。
  • array_diff_key() 的第二个参数声明的数组中,值是完全无关紧要的 -- 它们可以是null999 或者'eleventeen',只要键被尊重即可。
  • array_filter() 相比,array_diff_key() 没有任何作用域挑战,因为没有调用自定义函数。
  • 它可以写成一行代码。
  • 使用时无需检查索引是否存在 -- 如果缺少索引,则不会出现错误。

3
使用array_splice()函数。
array_splice( $b, 1, 1 );
// $b == Array ( [0] => 123 [1] => 789 [2] => 123 )

1

还没有人提到这一点,所以我来说一下:sort() 是你的好朋友。

$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach($fruits as $key => $val)
  echo "fruits[$key] = $val";

输出:

fruits[0] = apple

fruits[1] = banana

fruits[2] = lemon

fruits[3] = orange

// remove Lemon, too bitter
unset($fruits[2]);
// keep keys with asort
asort($fruits);
foreach($fruits as $key => $val)
  echo "fruits[$key] = $val";

输出:

fruits[0] = apple

fruits[1] = banana

fruits[3] = orange

这是您想要使用的重新索引键的方法:

// reindex keys with sort
sort($fruits);
foreach($fruits as $key => $val)
  echo "fruits[$key] = $val";

输出:

fruits[0] = apple

fruits[1] = banana

fruits[2] = orange

这个答案只在不会通过干扰元素顺序来破坏输出的情况下有限的适用。我担心这种技术会带来更多的负面影响。 - mickmackusa

0
如果您想从特定位置删除数组中的一个项目,可以获取该位置的键,然后取消设置它:
$b = array(123,456,789,123);
$p = 2;
$a = array_keys($b);
if ($p < 0 || $p >= count($a))
{
    throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
$k = $a[$p-1];
unset($b[$k]);

这适用于任何 PHP 数组,无论索引从哪里开始或者是否使用字符串作为键。

如果您想重新排列剩余的数组,只需使用array_values

$b = array_values($b);

这将为您提供一个从零开始的、数字索引的数组。

如果原始数组也是一个从零开始的、数字索引的数组(就像您的问题中一样),您可以跳过获取键的部分:

$b = array(123,456,789,123);
$p = 2;
if ($p < 0 || $p >= count($b))
{
    throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
unset($b[$p-1]);
$b = array_values($b);

或者直接使用 array_splice,它处理偏移量而不是键 并且 重新索引数组(输入的数字键不会保留):
$b = array(123,456,789,123);
$p = 2;
if ($p < 0 || $p >= count($b))
{
    throw new RuntimeException(sprintf('Position %d does not exists.', $p));
}
array_splice($b, $p-1, 1);

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