Jump to content

Array - remove every Nth key starting from X


silkfire

Recommended Posts

I can't for the life of me understand how to perform this so I need some professional help here.

 

I have a large array that contains some garbage every Nth and Nth + 1 element that needs to go away. array_filter doesn't work with keys but anyhow, i wouldn't know how to design the function.

 

My keys are numeric, starting from 0. The keys I want to remove are part of this sequence: 8, 9, 18, 19, 28, 29 ...

 

Can someone help me design a generic function to remove these keys?

 

function filter_keys($array, $n, $offset) {}

 

$new_array = filter_keys($array, 10, 8 );

 

I would maybe have to run this function twice, once for 8 offset and once for 9 offset.

Link to comment
Share on other sites

<?php
function filter_keys(&$array, $n, $offset)
{
for($i = $offset; $i < count($array); $i = $i+$n)
{
	unset($array[$i]);
	unset($array[$i + 1]); //For a more generic function, remove this and then call the function twice.
}
}

Passing the array by reference removes the need to return the function.  I haven't tested it.

Link to comment
Share on other sites

I'm not sure why it's important this be generic. 

 

// offsets is an array of the offsets you want to remove.
// In your example, you would want the $offsets to be 9, 10
function filter_keys(&$array, $offsets) {
  $count = 1;
  foreach ($array as $key) {
     foreach ($offsets as $offset) {
       if ($count % $offset == 0) {
          unset($array[$count - 1]);
       }       
     }
     $count++;
  }
}

// You'd call like this:

filter_keys($array, array(9, 10));

 

 

 

Link to comment
Share on other sites

You should not use "count($array)" inside the for() loop:

 

1) it would need to be executed on each loop and is not efficient.

2) It will cause the function not to work properly! On every iteration the count() is changing and would cause the loop to exit prematurely. That is also why running separate times fo the 8's and the 9's would also be problematic.

 

function filter_keys(&$array, $n, $offset)
{
    $arrayCount = count($array);
   for($i = $offset; $i < $arrayCount; $i+=$n)
   {
      unset($array[$i]);
      unset($array[$i + 1]); //For a more generic function, remove this and then call the function twice.
   }
}

Link to comment
Share on other sites

To expand, everything except the first argument in the for loop will be executed at every loop

 

for( {executed once at the start}; {executed every time the loop starts}; {executed every time the loop ends} )

 

So, if you put any function in either the second or third arguments, they will be executed every loop. Using count() in the for not only forces it to be executed every loop, but if you're changing the array, the value returned by count() will change... as mjdamato already stated.

Link to comment
Share on other sites

What about gizmola's solution?

 

 

Also, what's bad about using count() inside for() ?

My array had ~ 650 elements. It means it has to calculate count($array) 650 times, instead of once and then saving it to the variable.

 

More importantly, in this specific implementation, the bigger problem was that count() of the array would change on each iteration which would cause the loop to exit prematurely. To make it simpler. Let's say we had an array of 10 elements (0-9) and the loop will remove every odd element starting at 1

for($i = 1; $i < count($array); $i = $i+2)
{
    unset($array[$i]);
}

 

On the first iteration $i=1 and the count=10, so the item at index 1 is unset

On the second iteration $i=3 and the count=9, so the item at index 3 is unset

On the third iteration $i=5 and the count=8, so the item at index 5 is unset

On the fourth iteration $i=7 and the count=7, the for loop is exited since $i is not < the count of the array.

 

Both the indexes at 7 and 9 should have been removed, but they would not be since count() is being calculated on each iteration. But, as already stated it is poor standard to put a calculation in the parameters of the for loop that are calculated on each iteration - if they really shouldn't be calculated. There are instances where doing so would make sense. This just isn't one of them.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.