Home > Software design >  Array elements permutations with preserving keys in PHP
Array elements permutations with preserving keys in PHP

Time:07-23

I have an array:

[0 => 'перший', 1 => 'другий', 2 => 'третій']

I need to get:

[0 => 'перший', 1 => 'другий', 2 => 'третій'],
[0 => 'перший', 2 = > 'третій', 1 => 'другий'],
[1 => 'другий, 0 => 'перший', 2 => 'третій'],
[1 => 'другий ', 2 = > 'третій, 0 => 'перший'],
[2 => 'третій', 0 => 'перший', 1 = > 'другий'],
[2 => 'третій', 1 => 'другий', 0 = > 'перший']

I wrote a function:

function permutations($inArray, &$returnArray = [], $inProcessedArray = [])
{
    if (count($inArray) === 1)
    {
        $returnArray[] = array_merge($inProcessedArray, $inArray);
    }
    else
    {
        foreach($inArray as $key => $value)
        {
            $copyArray = $inArray;
            unset($copyArray[$key]);
            permutations($copyArray, $returnArray, array_merge($inProcessedArray, [$key => $value]));
        }
    }
}

But this returns array elements permutations without preserving keys
Any suggestions? Thanks in advance

CodePudding user response:

Using the generator permutations from: https://stackoverflow.com/a/27160465/

$hash = [
    0=>'Apple',
    1=>'Banana',
    2=>'Peach'
];

function permutations(array $elements)
{
    if (count($elements) <= 1) {
        yield $elements;
    } else {
        foreach (permutations(array_slice($elements, 1)) as $permutation) {
            foreach (range(0, count($elements) - 1) as $i) {
                yield array_merge(
                    array_slice($permutation, 0, $i),
                    [$elements[0]],
                    array_slice($permutation, $i)
                );
            }
        }
    }
}

$result = [];
foreach(permutations(array_keys($hash)) as $keys) {
    $row = [];
    foreach($keys as $k) {
        $row[$k] = $hash[$k];
    }
    $result[] = $row;
}
var_export($result);

Output:

array (
  0 => 
  array (
    0 => 'Apple',
    1 => 'Banana',
    2 => 'Peach',
  ),
  1 => 
  array (
    1 => 'Banana',
    0 => 'Apple',
    2 => 'Peach',
  ),
  2 => 
  array (
    1 => 'Banana',
    2 => 'Peach',
    0 => 'Apple',
  ),
  3 => 
  array (
    0 => 'Apple',
    2 => 'Peach',
    1 => 'Banana',
  ),
  4 => 
  array (
    2 => 'Peach',
    0 => 'Apple',
    1 => 'Banana',
  ),
  5 => 
  array (
    2 => 'Peach',
    1 => 'Banana',
    0 => 'Apple',
  ),
)

CodePudding user response:

This is over-egging the pudding somewhat. But given such a small array, we can loop over many combinations and filter accordingly.

I'm sure there is something more elegant, but this does the trick.

<?php
$result = [];
for($i=0; $i<3; $i  ) {
    for($j=0; $j<3; $j  ) {
        for($k=0; $k<3; $k  ) {
            $row = [$i=>$hash[$i], $j=>$hash[$j], $k=>$hash[$k]];                       
            if(count($row) == 3)
                $result[] = $row;
        }
    }
}

Output:

array (
  0 => 
  array (
    0 => 'Apple',
    1 => 'Banana',
    2 => 'Peach',
  ),
  1 => 
  array (
    0 => 'Apple',
    2 => 'Peach',
    1 => 'Banana',
  ),
  2 => 
  array (
    1 => 'Banana',
    0 => 'Apple',
    2 => 'Peach',
  ),
  3 => 
  array (
    1 => 'Banana',
    2 => 'Peach',
    0 => 'Apple',
  ),
  4 => 
  array (
    2 => 'Peach',
    0 => 'Apple',
    1 => 'Banana',
  ),
  5 => 
  array (
    2 => 'Peach',
    1 => 'Banana',
    0 => 'Apple',
  ),
)
  • Related