Удалить каждый n-й элемент из массива

Я хочу сбросить каждый второй элемент из массива. Меня не волнует, переупорядочены ли ключи или нет.

Конечно, я хочу это быстро и элегантно. Возможно ли это без цикла и временных переменных?

6 ответов

Мое собственное решение пока:

for ( $i = 1; isset($arr[$i]); $i += 2) { 
    unset($arr[$i]);
}

Преимущество состоит в том, что ему не нужно выражение if, а в том, что переменная ($i) по-прежнему необходимо, и оно работает, только если ключи числовые и без пробелов.

$n = 1
for( $i=$n;$i=$n;)
    {
        unset($arOne[$i]); 
        unset($arSnd[$i]);
        unset($arThd[$i]);
        break;
    }

Я думаю, что это тоже отлично.

Еще одно решение без цикла:

$arr = array('a', 'b', 'c', 'd', 'e');
$arr = array_filter( $arr, function($k) { return $k % 3 === 0; }, ARRAY_FILTER_USE_KEY);

Pro, это не нуждается в петле. Минусы, это намного медленнее, чем моя другая версия (с циклом for), выглядит немного страшно и снова зависит от клавиш.

 function arr_unset_sec(&$arr, $key)
 {
   if($key%2 == 0)
   {
     unset($arr[$key]);  
   }
 }
 array_walk($arr, 'arr_unset_sec');

Предполагая, что $arr может быть некоторым массивом. Проверьте этот кусок кода.

Я предоставлю два метода (array_filter() и foreach() цикл), который будет использовать условие $i++%$n нацеливаться на элементы, которые будут удалены.

Оба метода будут работать с индексированными и ассоциативными массивами.

  1. $i++ Это постинкремент. По сути, значение будет оцениваться сначала, а затем увеличиваться во вторую.
  2. % Это оператор по модулю - он возвращает "остаток" от деления значения левой стороны от значения правой стороны.
  3. Возвращаемое значение из условия будет либо 0 или положительное целое число. По этой причине для преобразования можно использовать встроенную в php функцию "жонглирование типов". 0 в false и натуральные числа как true,
  4. в array_filter() метод, use() синтаксис должен использовать &$i так что переменная является "модифицируемой". Без &, $i останется статичным (не зависит от постинкрементации).
  5. в foreach() метод, условие инвертировано !() по сравнению с array_filter() метод. array_filter() хочет знать, что "держать"; foreach() хочет знать что unset(),

Код: ( Демо)

//                          if:$n=2        $n=3        $n=4        $n=5
$array=['first'=>1,
        2,                  // remove
        'third'=>3,         //             remove
        'fourth'=>4,        // remove                  remove
        5,                  //                                     remove
        6,                  // remove      remove
        'seventh'=>7,
        'eighth'=>8,        // remove                  remove
        'ninth'=>9];        //             remove

// if $n is 0 then don't call anything, because you aren't attempting to remove anything
// if $n is 1 then you are attempting to remove every element, just re-declare as $array=[]

for($n=2; $n<5; ++$n){
    $i=1;  // set counter
    echo "Results when filtering every $n elements: ";
    var_export(array_filter($array,function()use($n,&$i){return $i++%$n;}));
    echo "\n---\n";
}

echo "\n\n";
// Using a foreach loop will be technically faster (only by a small margin) but less intuitive compared to
// the literal/immediate interpretation of "array_filter".

for($n=2; $n<5; ++$n){
    $i=1;
    $copy=$array;
    foreach($copy as $k=>$v){
        if(!($i++%$n)) unset($copy[$k]);  // or $i++%$n==0 or $i++%$n<1
    }
    echo "Results when unsetting every $n elements: ";
    var_export($copy);
    echo "\n---\n";
}

Выход:

Results when filtering every 2 elements: array (
  'first' => 1,
  'third' => 3,
  1 => 5,
  'seventh' => 7,
  'ninth' => 9,
)
---
Results when filtering every 3 elements: array (
  'first' => 1,
  0 => 2,
  'fourth' => 4,
  1 => 5,
  'seventh' => 7,
  'eighth' => 8,
)
---
Results when filtering every 4 elements: array (
  'first' => 1,
  0 => 2,
  'third' => 3,
  1 => 5,
  2 => 6,
  'seventh' => 7,
  'ninth' => 9,
)
---


Results when unsetting every 2 elements: array (
  'first' => 1,
  'third' => 3,
  1 => 5,
  'seventh' => 7,
  'ninth' => 9,
)
---
Results when unsetting every 3 elements: array (
  'first' => 1,
  0 => 2,
  'fourth' => 4,
  1 => 5,
  'seventh' => 7,
  'eighth' => 8,
)
---
Results when unsetting every 4 elements: array (
  'first' => 1,
  0 => 2,
  'third' => 3,
  1 => 5,
  2 => 6,
  'seventh' => 7,
  'ninth' => 9,
)
---

Если у вас есть массив, как

Array
(
    [0] => test1
    [1] => test2
    [2] => test3
    [3] => test4
    [4] => test5
)

Тогда вы можете перейти с кодом ниже. Это удалит каждый второй элемент массива.

$i = 1;
foreach ($demo_array as $key => $row) {
    if($i%2 == '0')
    {
        unset($demo_array[$key]);
    }
    $i++;
}

Надеюсь, это поможет вам. Дай мне знать, если тебе понадобится дополнительная помощь.

Другие вопросы по тегам