0

I want to unset every second item from an array. I don't care about if the keys are reordered or not.

Of course I want it fast and elegant. Is it maybe possible without a loop and temporary variables?

flori
  • 14,339
  • 4
  • 56
  • 63

6 Answers6

1

My own solution so far:

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

The pro is, that it needs no if-statement, the con that a variable ($i) is still needed and it works only if the keys are numeric and without gaps.

flori
  • 14,339
  • 4
  • 56
  • 63
  • I guess this is the only way. But a correction would be for($i = 2; $i < len($arr); $i + = 2){ isset($arr[$i]?unset($arr[$i]))} Because lets assume the 4th cell is unset already. The loop will exit then and there it wont go to the length – Abhilash Cherukat Feb 04 '15 at 11:08
  • @AbhilashCherukat Thanks, I changed the description. – flori Feb 04 '15 at 11:20
0

If you have an array like

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

Then you can go with below code. It will remove every second item of array.

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

Hope this will helps you. Let mee know if you need any further help on it.

  • The pro is, this version works with all kinds of keys. However I don't understand why the 0 is a string? – flori Feb 04 '15 at 11:24
  • Yes this will work with all kind of keys. Also we can directly use it as 0 but it's good habit to compare value with double quote. –  Feb 04 '15 at 11:28
  • @PHPWeblineindia Why in the world would it be a good habit to compare a variable which can only be a number against a string? – mickmackusa Dec 12 '17 at 06:08
0
 function arr_unset_sec(&$arr, $key)
 {
   if($key%2 == 0)
   {
     unset($arr[$key]);  
   }
 }
 array_walk($arr, 'arr_unset_sec');

Assuming $arr may be some array. Check this piece of code.

Harish Lalwani
  • 754
  • 5
  • 20
0

Another solution without a loop:

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

Pro, it needs no loop. Cons, it is a lot slower than my other version (with a for loop), looks a bit scary and depends again on the keys.

flori
  • 14,339
  • 4
  • 56
  • 63
0

I'll provide two methods (array_filter() and a foreach() loop) which will leverage the condition $i++%$n to target the elements to be removed.

Both methods will work on indexed and associative arrays.

  1. $i++ This is post-incrementation. Effectively, the value will be evaluated first, then incremented second.
  2. % This is the modulo operator - it returns the "remainder" from the division of the leftside value from the rightside value.
  3. The return value from the condition will either be 0 or a positive integer. For this reason, php's inherent "type juggling" feature can be used to convert 0 to false and positive integers as true.
  4. In the array_filter() method, the use() syntax must use &$i so that the variable is "modifiable". Without the &, $i will remain static (unaffected by post-incrementation).
  5. In the foreach() method, The condition is inverted !() in comparison to the array_filter() method. array_filter() wants to know what to "keep"; foreach() wants to know what to unset().

Code: (Demo)

//                          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";
}

Output:

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,
)
---
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0
$n = 1
for( $i=$n;$i=$n;)
    {
        unset($arOne[$i]); 
        unset($arSnd[$i]);
        unset($arThd[$i]);
        break;
    }

I think this will also perfectly.

imrahul
  • 41
  • 6