ThomasReggi
ThomasReggi

Reputation: 59495

Move all odd-keyed elements to the back of the array

I have an array with numeric keys and I need to move all elements with odd keys to the end of the array.

[
    0 => 'apples',
    1 => 'oranges',
    2 => 'peaches',
    3 => 'pears',
    4 => 'watermelon'
]

What I am looking to do is something like this

[
    0 => 'apples',
    2 => 'peaches',
    4 => 'watermelon',
    1 => 'oranges',
    3 => 'pears'
]

It does not matter if the array keys change or not, I just need the location of the values to change.

Upvotes: 0

Views: 360

Answers (4)

mickmackusa
mickmackusa

Reputation: 48031

A full-scale, stable sorting algorithm is not necessary for this task. Just isolate a filtered array containing elements with even keys, then use the array union operator (+) to append all odd elements to the result. $k & 1 is a bitwise odd number check. Demo

var_export(
    array_filter($array, fn($k) => !($k & 1), ARRAY_FILTER_USE_KEY) + $array
);

Or with a custom key sorting algorithm: Demo

uksort($array, fn($a, $b) => !($b & 1) <=> !($a & 1));
var_export($array);

See similar content at: Move all empty values to the back of the array

Upvotes: 0

user187291
user187291

Reputation: 53950

many options, for example:

foreach($a as $n => $v)
    $out[(($n & 1) << 24) | $n] = $v;
ksort($out);

or

foreach($a as $n => $v)
    $out[$n & 1][] = $v;
$out = array_merge($out[0], $out[1]);

Upvotes: 0

FtDRbwLXw6
FtDRbwLXw6

Reputation: 28929

<?php
$fruit = array('apples', 'oranges', 'peaches', 'pears', 'watermelon');

function fruitCmp($a, $b) {
    if ($a == $b) {
        return 0;
    }

    $aIsOdd = $a % 2;
    $bIsOdd = $b % 2;

    if (($aIsOdd && $bIsOdd) || (!$aIsOdd && !$bIsOdd)) {
        return $a < $b ? -1 : 1;
    }

    if ($aIsOdd && !$bIsOdd) {
        return 1;
    }

    if (!$aIsOdd && $bIsOdd) {
        return -1;
    }
}

uksort($fruit, 'fruitCmp');

var_dump($fruit);

Output:

array(5) {
  [0]=>
  string(6) "apples"
  [2]=>
  string(7) "peaches"
  [4]=>
  string(10) "watermelon"
  [1]=>
  string(7) "oranges"
  [3]=>
  string(5) "pears"
}

Upvotes: 2

AVProgrammer
AVProgrammer

Reputation: 1350

Hmm, try something like this:

<?php
$fruits = array('apples', 'oranges', 'peaches', 'pears', 'watermelon');
$odds = array();
$evens = array();

for($i = 0; $i < count($fruits); $i++){
    if($i % 2){
        $odds[] = $fruits[$i];
    } else {
        $evens[] = $fruits[$i];
    }
}
?>

You will end up with two arrays, you can work on the odds as you wish, then combine the arrays (appending odds to evens with: $combined = $evens + $odds;).

Upvotes: 1

Related Questions