4

How can I move the empty values of an array to its last position?

For example:

$givenArray = array( 
                    0=>'green', 
                    1=>'', 
                    2=>'red', 
                    3=>'', 
                    4=>'blue'
                  );

$requiredArray = array(
                       0=>'green',
                       1=>'red',
                       2=>'blue',
                       3=>'',
                       4=>'' 
                      );

Provided that the non empty values should not be sorted. It should be as it is, i.e. only the empty values should move to the end of an array.

I need exactly what my examples show.

hakre
  • 193,403
  • 52
  • 435
  • 836
Raja
  • 149
  • 1
  • 2
  • 9
  • I think you picked the wrong answer as answer... Hakre's answer is definitely best way to go and apparently that did work for you. – Tim S. Feb 23 '12 at 08:20

6 Answers6

7

You are looking for all values not being an empty string ("") first and then all values being an empty string:

$requiredArray = array_diff($givenArray, array('')) 
                 + array_intersect($givenArray, array(''));

This will give you:

array(5) {
  [0]=> string(5) "green"
  [2]=> string(3) "red"
  [4]=> string(4) "blue"
  [1]=> string(0) ""
  [3]=> string(0) ""
}

Which has the benefit that it preserves key => value association. If you need to renumber the keys, just apply the array_values function:

$requiredArray = array_values($requiredArray);

This will turn it into your required layout (Demo):

array(5) {
  [0]=> string(5) "green"
  [1]=> string(3) "red"
  [2]=> string(4) "blue"
  [3]=> string(0) ""
  [4]=> string(0) ""
}
hakre
  • 193,403
  • 52
  • 435
  • 836
  • I upvoted your answer for simplicity, originality and best functionality. Of all answers, this is the best way to go. – Tim S. Feb 22 '12 at 13:56
6

There are much better/more elegant answers in this thread already, but this works too:

//strip empties and move to end
foreach ($givenArray as $key => $value)
{ 
    if ($value === "")
    { 
        unset($givenArray[$key]);
        $givenArray[] = $value;
    }
}

// rebuild array index
$givenArray = array_values($givenArray);

Codepad demo

hakre
  • 193,403
  • 52
  • 435
  • 836
jon
  • 5,986
  • 5
  • 28
  • 35
  • 1
    I compacted the code-example. FYI: Foreach is iterating over an array copy, so you don't need to iterate twice for the operation. – hakre Feb 23 '12 at 10:20
5

Try using usort.

function empty_sort ($a, $b) {
    if ($a == '' && $b != '') return 1;
    if ($b == '' && $a != '') return -1;
    return 0; 
}

usort($array, 'empty_sort');

Which gives (Demo):

Array
(
    [0] => blue
    [1] => green
    [2] => red
    [3] => 
    [4] => 
)
hakre
  • 193,403
  • 52
  • 435
  • 836
gintas
  • 2,118
  • 1
  • 18
  • 28
  • you want to swap `-1` and `1`, I think. Also, this won't leave the non-empty elements in the same order. – Tim Feb 22 '12 at 13:18
  • Did not realise PHP does not do stable sorting. Here is a stable version of usort: http://stackoverflow.com/a/4353844/1220966 – gintas Feb 22 '12 at 13:23
2

This should work:

function sortempty( $a, $b ) {
    return empty( $a );
}

usort( $array, 'sortempty' );

Output (Demo):

Array
(
    [0] => blue
    [1] => green
    [2] => red
    [3] => 
    [4] => 
)

usort() allows you to sort an array using a user-defined function. I return if $a is empty or not. If it's empty, return 1 which makes value $a shift right (or down) in the array.

hakre
  • 193,403
  • 52
  • 435
  • 836
Tim S.
  • 13,597
  • 7
  • 46
  • 72
  • Thanks for your reply, but I'm getting the result like this Array Array ( [0] => blue [1] => green [2] => red [3] => [4] => ) here the values are getting sorted. but it should be like this ( [0] => green [1] => red [2] => blue [3] => [4] => ) – Raja Feb 22 '12 at 13:29
  • @Raja I think that's a side-effect of using `usort()`. If you return 0 at all times, it still sorts alphabetically. – Tim S. Feb 22 '12 at 13:53
1
$givenArray = array(
                    0=>'green',
                    1=>'',
                    2=>'red',
                    3=>'',
                    4=>'blue'
                  );

foreach($givenArray as $value){
    if(empty($value)){
        $newarray[] = $value;
    }else{
        $filledarray[] = $value;
    }
}
$requiredArray = array_merge($filledarray,$newarray);
Poonam
  • 4,591
  • 1
  • 15
  • 20
0

There is usort($array, $callback) function that will sort with your own custom callback.

German Rumm
  • 5,782
  • 1
  • 25
  • 30