Tetris-ing an array

后端 未结 16 1410
时光取名叫无心
时光取名叫无心 2021-01-30 15:38

Consider the following array:

/www/htdocs/1/sites/lib/abcdedd
/www/htdocs/1/sites/conf/xyz
/www/htdocs/1/sites/conf/abc/         


        
16条回答
  •  星月不相逢
    2021-01-30 15:56

    Well, considering that you can use XOR in this situation to find the common parts of the string. Any time you xor two bytes that are the same, you get a nullbyte as the output. So we can use that to our advantage:

    $first = $array[0];
    $length = strlen($first);
    $count = count($array);
    for ($i = 1; $i < $count; $i++) {
        $length = min($length, strspn($array[$i] ^ $first, chr(0)));
    }
    

    After that single loop, the $length variable will be equal to the longest common basepart between the array of strings. Then, we can extract the common part from the first element:

    $common = substr($array[0], 0, $length);
    

    And there you have it. As a function:

    function commonPrefix(array $strings) {
        $first = $strings[0];
        $length = strlen($first);
        $count = count($strings);
        for ($i = 1; $i < $count; $i++) {
            $length = min($length, strspn($strings[$i] ^ $first, chr(0)));
        }
        return substr($first, 0, $length);
    }
    

    Note that it does use more than one iteration, but those iterations are done in libraries, so in interpreted languages this will have a huge efficiency gain...

    Now, if you want only full paths, we need to truncate to the last / character. So:

    $prefix = preg_replace('#/[^/]*$', '', commonPrefix($paths));
    

    Now, it may overly cut two strings such as /foo/bar and /foo/bar/baz will be cut to /foo. But short of adding another iteration round to determine if the next character is either / or end-of-string, I can't see a way around that...

提交回复
热议问题