Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping even numbered elements of an array?

Tags:

arrays

php

Say I have an $input array, that contains something like this :

array
  0 => string 'a' (length=1)
  1 => string 'b' (length=1)
  2 => string 'c' (length=1)
  3 => string 'd' (length=1)
  4 => string 'e' (length=1)
  5 => string 'f' (length=1)
  6 => string 'g' (length=1)
  7 => string 'h' (length=1)
  8 => string 'i' (length=1)
  9 => string 'j' (length=1)

I want to get an $output array, that would contain this :

array
  0 => string 'a' (length=1)
  1 => string 'c' (length=1)
  2 => string 'e' (length=1)
  3 => string 'g' (length=1)
  4 => string 'i' (length=1)

The $output array contains half the values that were in $input ; those that had even numbered keys in the input; the first one is kept, second one is not, third one is, and so one...

(Note: the keys are not preserved ; only the values are important)

How could I do that ? Keeping only one on two values of the array ?


I have already tried some ideas, and already have a couple different solutions :

First idea: iterate over the input array, and copy the interesting values to the output array:

$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = array();

$nbr = count($input);
for ($i = 0 ; $i < $nbr ; $i += 2) {
    $output[] = $input[$i];
}

var_dump(array_values($output));

Second idea: iterate over the array, and unset what I don't want to keep:

$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = $input;

$nbr = count($input);
for ($i = 1 ; $i < $nbr ; $i += 2) {
    unset($output[$i]);
}

var_dump(array_values($output));

Third idea: use a combinaison of array_flip, range, array_diff_key, ... :

$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = array();

$keys_to_exclude = array_flip(range(1, count($input)-1, 2));
$output = array_diff_key($input, $keys_to_exclude);

var_dump(array_values($output));

Fourth idea: about the same thing, but with array_intersect_key:

$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = array();

$keys_to_include = array_flip(range(0, count($input)-1, 2));
$output = array_intersect_key($input, $keys_to_include);

var_dump(array_values($output));

Any other idea ? Even / particularly if it sounds kinda hacky or anything ?

My goal is not to get the most efficient nor simple syntax ; it's just for fun and because I am curious, actually ^^

If the title is not using the right words to describe what I want, don't hesitate to tell ; or edit it :-)

like image 989
Pascal MARTIN Avatar asked Aug 02 '09 10:08

Pascal MARTIN


2 Answers

<?php
$x = range('a', 'f');

$x = array_map('array_shift', 
       array_chunk($x, 2)
     );

var_dump($x);

or another one

<?php
class ArrayEvenIterator extends ArrayIterator {
    public function next() {
        parent::next();
        return parent::next();
    }
}

$x = range('a', 'f');
$x = iterator_to_array(new ArrayEvenIterator( $x ), false);

var_dump($x);

or with a php 5.3 closure (which isn't better than global in this case ;-) )

<?php
$x = range('a', 'f');

$x = array_filter( $x, function($e) use(&$c) { return 0===$c++%2; });

var_dump($x);
like image 115
VolkerK Avatar answered Sep 24 '22 12:09

VolkerK


Assuming numeric keys:

foreach ($array as $key => $value) {
    if ($key % 2 != 0) {
        unset($array[$key]);
    }
}

EDIT

Here goes my slightly more insane solution which keeps the index continuous without re-indexing. ;o)

foreach ($array as $key => $value) {
    if (!($key%2)) {
        $array[$key/2] = $value;
    }
}
$array = array_slice($array, 0, ceil(count($array)/2));
like image 32
deceze Avatar answered Sep 22 '22 12:09

deceze