-1

I've got following array, and what I'm trying to achieve is remove all null values after i value.

Original array:

$a = ["a", "b", null, null, null, null, "i", null, null, null, null];

Desired result:

$a = ["a", "b", null, null, null, null, "i"];

Things I've tried: So I had an idea, to filter array from empty values using array_filter, get index of the last value, then get index of the last item in the original array, and unset that range using for loop, but that does not seems like an efficient solution to me. So my question is are there any other, more efficient ways of achieving that? Thanks.

Ed T.
  • 325
  • 2
  • 12

5 Answers5

1

array_pop() lets you grab elements off the end of an array; you can continue doing this until you find a non-null element or the array is empty.

// This version modifies the array in-place
function remove_trailing_nulls(&$arr) {
  while($arr) {
    $last = array_pop($arr);
    if($last !== null) {
      // Re-add the non-null element that was removed, and we're done
      $arr[] = $last;
      return;
    }
  }
}

// This version returns a new copy of the array
function without_trailing_nulls($arr) {
  while($arr) {
    $last = array_pop($arr);
    if($last !== null) {
      // Re-add the non-null element that was removed, and we're done
      $arr[] = $last;
      break;
    }
  }
  return $arr;
}
Amber
  • 507,862
  • 82
  • 626
  • 550
  • Thanks for the detailed answer, that does work quite well! But, after doing some benchmarking, I'll go for reversed for loop option, as it seems a bit quicker. – Ed T. Jan 21 '19 at 23:20
  • 1
    No worries. Hope other people will benefit from the explanation as well. – Amber Jan 21 '19 at 23:27
1

The array_filter() method will only work if all the non-null values are unique. If there are duplicates, array_search() will find the first of them, not the last.

You can use a for loop that goes from the end until it finds a non-null entry:

for ($i = count($a)-1; $i >= 0 && $a[$i] === null; $i--) {
    unset($a[$i]);
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • After re-reading the question, I'm guessing array_search won't actually work anyway as the last value is potentially variable looking at the title. – Jonnix Jan 21 '19 at 22:59
  • @JonStirling It would work because his idea was `array_search(last($filtered), $a)`. So the variable value will be found. – Barmar Jan 21 '19 at 23:03
  • True, was thinking more on it's own, but you're obviously right :P – Jonnix Jan 21 '19 at 23:08
  • Not sure who downvoted this answer, as it's one of the most pragmatic and fastest ways of achieving set goal, to my knowledge. And I've completely forgot about reversed loop option... – Ed T. Jan 21 '19 at 23:16
0

Just use array_filter function:

$result = array_filter($arr, function($v, $k) use($arr) {
    $iKey = array_search('i', $arr);
    if(($iKey >= $k) || ($iKey < $k && !$v))
        return $v;
}, ARRAY_FILTER_USE_BOTH)

As mentioned in comment if i can be anything you could simply do the following single liner ;) :

var_dump(array_slice($arr, 0, array_search(end(array_filter($arr)),$arr)+1));
Nishanth Matha
  • 5,993
  • 2
  • 19
  • 28
  • 1
    I don't think the last element will always be `i`, that's just an example. – Barmar Jan 21 '19 at 23:03
  • Your second method is what he described in the question. – Barmar Jan 22 '19 at 00:32
  • @Barmar The actual question was about performance and my second solution is quite efficient as your solution (confirmed with `microtime` as well as `xdebug`) . So, I guess that doesn't deserve a down vote ;) – Nishanth Matha Jan 23 '19 at 22:21
  • The downvote was for looking specifically for the string `i`. – Barmar Jan 23 '19 at 22:26
0
$found = false;
$item = "i";
$a = ["a", "b", null, null, null, null, "i", null, null, null, null];
print_r(array_filter($a, function($value) { 
  if($value == $item) {
    $found = true;
  }
  return !$found || !is_null($value) 
}));

The idea is basically we start checking for null values after we have found our item.

wale
  • 96
  • 1
  • 3
-3
print_r(array_filter($linksArray, function($value) { return $value !== ''; }));

use array_filter() See more