Performance tips for finding unique permutation

前端 未结 5 1909
没有蜡笔的小新
没有蜡笔的小新 2020-12-24 08:05

TLDR: how to find multidimensional array permutation in php and how to optimize for bigger arrays?

This is continuation of this question: how to fin

5条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-24 08:40

    Based on the answer to the previous question you supplied this can be solved ( in that case ) way more elegantly using a few built-in functions PHP has for array support. Which is probably the best of any language.

    function solve($matrix){
        $master = [];
        $_matrix = [];
        foreach($matrix as $key => $array){
            $_matrix[$key] = array_combine($array,$array);
            $master += $_matrix[$key];
        }
        $default = array_fill_keys($master, ''); 
        $result = [];
        foreach($_matrix as $array){
            $result[] = array_values(array_merge($default, $array));
        }
        print_r($result);
    }
    

    Using their same tests

    $tests = [
        [ ['X'], ['X'] ],
        [ ['X'], ['X'], ['X'] ],
        [ [ 'X', '' ], [ '', 'X' ] ],
        [ ['X', 'Y', 'Z'], ['X', 'Y'], ['X']],
        [ ['X', 'Y'], ['X', 'Y'], ['X', 'Y'] ],
        [ ['X', 'Y', 'Z'], ['X', 'Y', 'Z'], ['X', 'Y', 'Z'] ],
        [ ['X', 'Y', 'Z', 'I', 'J'], ['X', 'Y', 'Z', 'I'], ['X', 'Y', 'Z', 'I'], ['X', 'Y', 'Z', 'I'], ['X', 'Y', 'Z'], ['X', 'Y', 'Z'] ],
    ];
    array_map(function ($matrix) {
        solve($matrix);
    }, $tests);
    

    This is what I get in comparison

    [
      0 => ['X', 'Y', 'Z', 'I', 'J'] //<- contains all unique values
      1 => ['X', 'Y', 'Z', 'I']
      2 => ['X', 'Y', 'Z', 'I']
      3 => ['X', 'Y', 'Z', 'I']
      4 => ['X', 'Y', 'Z']
      5 => ['X', 'Y', 'Z']
    ]
    Their Result:
    [
      0 => ['', 'X', 'Y', 'Z', 'I', 'J'] //<- contains an extra '' empty value
      1 => ['', '', 'X', 'Y', 'Z', 'I']
      2 => ['I', '', '', 'X', 'Y', 'Z']
      3 => ['Z', 'I', '', '', 'X', 'Y']
      4 => ['Y', 'Z', '', '', '', 'X']
      5 => ['X', 'Y', 'Z', '', '', '']
    ]
    My Result
    [
      0 => ['X', 'Y', 'Z', 'I', 'J']
      1 => ['X', 'Y', 'Z', 'I', '']
      2 => ['X', 'Y', 'Z', 'I', '']
      3 => ['X', 'Y', 'Z', 'I', '']
      4 => ['X', 'Y', 'Z','','']
      5 => ['X', 'Y', 'Z','','']
    ]
    

    You can test it here.

    http://sandbox.onlinephpfunctions.com/code/86d0b4332963f95449df2e7d4d47fcd8224fe45d

    I even timed it using microtime

    mine 0.00013017654418945 milliseconds

    theirs 0.10895299911499 milliseconds

    Which is not really a surprise, as theirs is around 60 lines of code and 7 function calls. Mine is only 1 function 14 lines of code.

    That said I don't know if the position of the values is important in the output. Nor exactly what you expect as the output extending that question.

    The fact is they also lose the index position, just look at the second array in their result, 2 => ['I', '', '', 'X', 'Y', 'Z'] compared to the input 2 => ['X', 'Y', 'Z', 'I']. And I won't mention the extra '' in the output that probably doesn't belong there.

    Maybe I'm missing something, lol, I don't typically do these math-y type things.

    UPDATE if you want an explanation of how this works,

    • array_combine($array,$array); creates an array with matched key => value, we abuse the fact that array keys are unique by nature. Like so ['X'=>'X','Y'=>'Y'...]
    • then we build a "master" array with all the values in it and matched keys, one array to rule them all. The master array is limited in size to the max number or unique values because we are using the keys to eliminate duplicates.
    • then we use array_fill_keys($master, ''); to sort of create a template of all the values. The keys of "master" are all the unique values in all of the inner arrays, so we fill it with our "wildcard" placeholder. In this case it looks like this ['X'=>'', 'Y'=>'', 'Z'=>'', 'I'=>'', 'J'=>'']
    • then we merge the "modified" original array, also abusing the array keys for our advantage, by replacing the placeholders in the "templated" master array with the "modified" original array, because the keys match.
    • last we strip the keys from the array using array_values

    And we are left with each inner array "templated" by the master array but with the original values filled in and the missing ones empty.

提交回复
热议问题