Consider the following array:
/www/htdocs/1/sites/lib/abcdedd
/www/htdocs/1/sites/conf/xyz
/www/htdocs/1/sites/conf/abc/
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...