0

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

1
  • So you are basically permuting the order and keeping the key/value association, right? If so, I think I'd make two total passes. The first would only permute the keys to get your different orders. The second would then build the output array taking the source array with the permuted key order. Commented Jul 22, 2022 at 14:29

2 Answers 2

1

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',
  ),
)
Sign up to request clarification or add additional context in comments.

1 Comment

If anyone can find a more elegant permutation function, please link or edit accordingly.
0

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',
  ),
)

Comments

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.