Giorgio
Giorgio

Reputation: 1970

Remove slices from array in PHP

I have a PHP array and I want to remove slices of elements with the following rule: when an element has visible=0, I want remove the element and the following elements after it, no matter if they are visible or not.

In this example, I would like to remove two, three, four, six and seven

$categories = array(
              array('id'=>'one','visible'=>1,'elements'=>2),
              array('id'=>'two','visible'=>0,'elements'=>2),
              array('id'=>'three','visible'=>0,'elements'=>1),
              array('id'=>'four','visible'=>1,'elements'=>3),
              array('id'=>'five','visible'=>1,'elements'=>2),
              array('id'=>'six','visible'=>0,'elements'=>1),
              array('id'=>'seven','visible'=>1,'elements'=>3),
              array('id'=>'eight','visible'=>1,'elements'=>2)
              );

I've tried the following snippet

foreach($categories as $i=>$data)
{
    if($data['visible']==0)
    {
        array_splice($categories, $i, $data['elements']);
    }
}

This is my expected result after slicing and the actual result

What am I missing?

Upvotes: 2

Views: 1018

Answers (3)

ilpaijin
ilpaijin

Reputation: 3695

A couple of alternatives more, using array_column (>php5.5.0) and array_filter:

foreach (array_column($categories, 'visible') as $k => $v) {
    if (!$v) {
        $categories[$k] = $categories[$k++] = null;
    }
}

$result = array_filter($categories);
var_dump($result);

Or with array_walk

array_walk(array_column($categories, 'visible'), function ($v, $k) use (&$categories) {
    if (!$v) {
        $categories[$k] = $categories[$k++] = null;
    }
});

$result = array_filter($categories);
var_dump($result);

Upvotes: 0

felipsmartins
felipsmartins

Reputation: 13549

Pretty easy:

$length  = count($categories);
$results = array();

for ($i = 0; $i < $length; $i++) {
    # just skip!
    if ($categories[ $i ]['visible'] == 0) {
        $i = ( $i + $categories[ $i ]['elements'] );        
    } else {
        array_push($results, $categories[$i]);
    }   
}

Upvotes: 1

axiac
axiac

Reputation: 72226

Run through $categories using a simple for() loop, copy the visible items to a new list ($cat), skip the not visible items and the specified number of items that follows them:

// Generate the filtered list here
$cat = array();

$count = count($categories);
for ($i = 0; $i < $count; $i ++) {
    $data = $categories[$i];
    if ($data['visible']) {
       // Copy visible item
       $cat[] = $data;
    } else {
       // Do not copy and skip the specified number of extra items
       $i += $data['elements'];
    }
}

echo("Expected: one, five, eight\n");
echo('Actual  : '.implode(', ', array_column($cat, 'id'))."\n");

Update

Your solution works too if you remove the correct number of items using array_splice(): they are 1 + $data['elements']; 1 is the item at index $i and the next $data['elements'] items.

foreach($categories as $i=>$data)
{
    if($data['visible']==0)
    {
        array_splice($categories, $i, 1 + $data['elements']);
    }
}

Upvotes: 2

Related Questions