Удалить фрагменты из массива в переполнении стека

У меня есть массив PHP, и я хочу удалить фрагменты элементов по следующему правилу: когда элемент имеет visible=0Я хочу удалить элемент и следующее elements после этого, неважно, видны они или нет.

В этом примере я хотел бы удалить two, three, four, six а также 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)
);

Я попробовал следующий фрагмент

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

Это мой ожидаемый результат после нарезки и фактический результат

  • Ожидаемый результат: one, five, eight
  • фактический: one, four, five, seven, eight

Что мне не хватает?

1

Решение

Пробежать через $categories используя простой for() цикл, скопировать видимые элементы в новый список ($cat), пропустите невидимые элементы и указанное количество элементов, следующих за ними:

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

Обновить

Ваше решение также работает, если вы удалите правильное количество элементов, используя array_splice(): они есть 1 + $data['elements']; 1 это элемент в индексе $i и следующий $data['elements'] Предметы.

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

Другие решения

Довольно легко:

$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]);
}
}
1

Еще пара альтернатив, используя array_column (> php5.5.0) и array_filter:

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

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

Или с 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);
0
По вопросам рекламы [email protected]