21

I have this array:

$array = array(a, b, c, d, e, f, g);

I want to split it in two arrays depending if the index is even or odd, like this:

$odd = array(a, c, e, g);

$even = array(b, d, f);

Thanks in advance!

1
  • The keys for b, d and f are 1, 3 and 5... are you sure they shouldn't be $odd? Commented Sep 13, 2012 at 12:04

10 Answers 10

44

One solution, using anonymous functions and array_walk:

$odd = array();
$even = array();
$both = array(&$even, &$odd);
array_walk($array, function($v, $k) use ($both) { $both[$k % 2][] = $v; });

This separates the items in just one pass over the array, but it's a bit on the "cleverish" side. It's not really any better than the classic, more verbose

$odd = array();
$even = array();
foreach ($array as $k => $v) {
    if ($k % 2 == 0) {
        $even[] = $v;
    }
    else {
        $odd[] = $v;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I've searched for some elegant solution, but finished with simple verbose solution. It's more easy for understanding and maintaining.
13

Use array_filter (PHP >= 5.6):

$odd = array_filter($array, function ($input) {return $input & 1;}, ARRAY_FILTER_USE_KEY);
$even = array_filter($array, function ($input) {return !($input & 1);}, ARRAY_FILTER_USE_KEY);

1 Comment

Unfortunately, this technique will be making two full passes over the input array. This disadvantage does not occur in the accepted answer -- both of Jon's solution make a single pass over the input array.
6

As an almost-one-liner, I think this will be my favourite:

$even = $odd = array();
foreach( $array as $k => $v )  $k % 2  ?  $odd[] = $v  :  $even[] = $v;

Or for a tiny little more? speed:

$even = $odd = array();
foreach( $array as $k => $v )  ( $k & 1 ) === 0  ?  $even[] = $v  :  $odd[] = $v;

A bit more verbose variant:

$both = array( array(), array() );
// or, if $array has at least two elements:
$both = array();

foreach( $array as $k => $v )  $both[ $k % 2 ][] = $v;
list( $even, $odd ) = $both;

With array_chunk:

$even = $odd = array();
foreach( array_chunk( $array, 2 ) as $chunk ){
  list( $even[], $odd[] ) = isset( $chunk[1]) ? $chunk : $chunk + array( null, null );
  // or, to force even and odd arrays to have the same count:
  list( $even[], $odd[] ) = $chunk + array( null, null );
}

If $array is guaranteed to have even number of elements:

$even = $odd = array();
foreach( array_chunk( $array, 2 ) as $chunk )
  list( $even[], $odd[] ) = $chunk;

PHP 5.5.0+ with array_column:

$chunks = array_chunk( $array, 2 );
$even = array_column( $chunks, 0 );
$odd  = array_column( $chunks, 1 );

Something similar for older PHP versions. The keys will be 0,2,4,… and 1,3,5,…. If you don't like this, apply an array_values too:

$even = array_intersect_key( $array, array_flip( range( 0, count( $array ), 2 )));
$odd  = array_intersect_key( $array, array_flip( range( 1, count( $array ), 2 )));

or

$even = array_intersect_key( $array, array_fill_keys( range( 0, count( $array ), 2 ), null ));
$odd  = array_intersect_key( $array, array_fill_keys( range( 1, count( $array ), 2 ), null ));

1 Comment

I like your array_chunk() with array_column() example, very clean. It does not require an even number of elements.
5

I am not sure if this is the most elegant way, but it should work a charm:

$odd=array();
$even=array();
$count=1;
foreach($array as $val)
{
    if($count%2==1)
    {
        $odd[]=$val;
    }
    else
    {
        $even[]=$val;
    }
    $count++;
}

Comments

2

One more functional solution with array_chunk and array_map. The last line removes empty item from the 2nd array, when size of a source array is odd

list($odd, $even) = array_map(null, ...array_chunk($ar,2));
if(count($ar) % 2) array_pop($even);

Comments

1

Just loop though them and check if the key is even or odd:

$odd = array();
$even = array();
foreach( $array as $key => $value ) {
    if( 0 === $key%2) { //Even
        $even[] = $value;
    }
    else {
        $odd[] = $value;
    }
}

Comments

1

One

$odd = $even = array();
for ($i = 0, $l = count($array ); $i < $l;) { // Notice how we increment $i each time we use it below, by two in total
    $even[] = $array[$i++];
    if($i < $l)
    {
       $odd[] = $array[$i++];
    }
}

Two

$odd = $even = array();
foreach (array_chunk($array , 2) as $chunk) {
    $even[] = $chunk[0];
    if(!empty( $chunk[1]))
    {
       $odd[] = $chunk[1];
    }
}

Comments

1

Based on @Jon's second variant, I made this following for use with PHP Smarty v3 template engine. This is for displaying news/blog with both one or two columns template model.

After the MySql query I'll do the following code :

if(sizeof($results) > 0) {
    $data = array();
    foreach($results as $k => $res) {
        if($k % 2 == 0) {
            $res["class"] = "even";
            $data["all"][] = $data["even"][] = $res;
        }
        else {
            $res["class"] = "odd";
            $data["all"][] = $data["odd"][] = $res;
        }
    }
}

I obtain an array of 3 sub-arrays (including odd/even class) with Smarty syntax of use :

  1. all items {foreach $data.all as $article}...{/foreach}
  2. odd items only {foreach $data.odd as $article}...{/foreach}
  3. even items only {foreach $data.even as $article}...{/foreach}

Hope it helps some people...

Comments

1
$odd = [];
$even = [];
while (count($arr)) {
    $odd[] = array_shift($arr);
    $even[] = array_shift($arr);
}

4 Comments

Please try to avoid just dumping code as an answer and try to explain what it does and why. Your code might not be obvious for people who do not have the relevant coding experience. Please edit your answer to include clarification, context and try to mention any limitations, assumptions or simplifications in your answer.
Nope I wasn't. Your answer was so short that it landed in the Low Quality Review Queue. No offense is meant by my comment, and your answer is not wrong, which is why I voted not to have it removed, but a basic explanation of what you are doing would be useful. One simple sentence will double the quality of your answer, which helps future new users, and improves your chances of a +1. It is a win-win situation.
I'm a simple man. I don't need votes. And I definitely don't care what "Quality Review" algorithm "thinks" I should do.
@DoubleThink, I feel ya. But the hope is that every fully explained answer, even if trivial, can learn a Padawan cleaner code. Allowing code masters a few more uninterrupted moments of code output to change the world. ;)
0
    <?php

$array1 = array(0,1,2,3,4,5,6,7,8,9);
$oddarray = array();
$evenarray = array();

$count = 1;

echo "Original: ";
foreach ($array1 as $value)
 {
    echo "$value";
}

echo "<br> Even: ";

foreach ($array1 as $print) 
{
    if ($count%2==1) 
    {
        $evenarray = $print;
        echo "$print";
    }
    $count++;
}

echo "<br> Odd: ";

foreach ($array1 as $print2) {
    if ($count%2!=1) 
    {
        $oddarray[] = $print2;
        echo "$print2";
    }
    $count++;
}

?>

Output:

Original: 0123456789
Even: 02468
Odd: 13579

4 Comments

Please explain what your block of code brings to the table.
there are two loops, one is for even indexes and another one is for odd indexes. As you can see in the output that it will print first the original array, then even array by first loop and then odd array by 2nd array. so the array has been divided into two parts, even and odd.
What I meant is, explain it as an addition to the answer.
I agree. This answer is missing its educational explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.