Рассмотрим следующий массив:
/www/htdocs/1/sites/lib/abcdedd
/www/htdocs/1/sites/conf/xyz
/www/htdocs/1/sites/conf/abc/def
/www/htdocs/1/sites/htdocs/xyz
/www/htdocs/1/sites/lib2/abcdedd
каков самый короткий и самый элегантный способ обнаружения общего базового пути - в данном случае
/www/htdocs/1/sites/
и удалить его из всех элементов массива?
lib/abcdedd
conf/xyz
conf/abc/def
htdocs/xyz
lib2/abcdedd
Ответы:
Напишите функцию,
longest_common_prefix
которая принимает на вход две строки. Затем примените его к строкам в любом порядке, чтобы уменьшить их до общего префикса. Поскольку он ассоциативен и коммутативен, порядок не имеет значения для результата.Это то же самое, что и для других двоичных операций, таких как, например, сложение или наибольший общий делитель.
источник
Загрузите их в trie-структуру данных. Начиная с родительского узла, посмотрите, у какого дочернего узла больше одного. Как только вы найдете этот волшебный узел, просто демонтируйте структуру родительского узла и сделайте текущий узел корневым.
источник
источник
/usr/lib
и/usr/lib2
он дал/usr/lib
как самый длинный общий путь, а не/usr/
). Я (надеюсь) исправил оба.Что ж, учитывая, что вы можете использовать
XOR
в этой ситуации, чтобы найти общие части строки. Каждый раз, когда вы исключаете два одинаковых байта, на выходе вы получаете нулевой байт. Итак, мы можем использовать это в наших интересах:После этого единственного цикла
$length
переменная будет равна самой длинной общей базовой части массива строк. Затем мы можем извлечь общую часть из первого элемента:И вот оно. Как функция:
Обратите внимание, что он использует более одной итерации, но эти итерации выполняются в библиотеках, поэтому в интерпретируемых языках это даст огромный выигрыш в эффективности ...
Теперь, если вам нужны только полные пути, нам нужно обрезать до последнего
/
символа. Так:Теперь он может перерезать две струны, например,
/foo/bar
и/foo/bar/baz
будет обрезан/foo
. Но короткие добавления другой итерации раунда , чтобы определить , если следующий символ является либо/
или с истекшим строки, я не могу видеть путь вокруг этого ...источник
Наивный подход заключался бы в том, чтобы взорвать пути
/
и последовательно сравнивать каждый элемент в массивах. Так, например, первый элемент будет пустым во всех массивах, поэтому он будет удален, следующий элемент будетwww
, он одинаков во всех массивах, поэтому он будет удален и т. Д.Что-то вроде (
непроверенный)После этого вам просто нужно снова взорвать элементы
$exploded_paths
:Что дает мне:
Это может плохо масштабироваться;)
источник
Хорошо, я не уверен, что это пуленепробиваемое, но я думаю, что это работает:
Это примет первое значение в массиве как ссылочную строку. Затем он будет перебирать ссылочную строку и сравнивать каждый символ с символом второй строки в той же позиции. Если символ не совпадает, ссылочная строка будет сокращена до позиции символа, и будет сравниваться следующая строка. Тогда функция вернет самую короткую совпадающую строку.
Производительность зависит от данных струн. Чем раньше станет короче ссылочная строка, тем быстрее завершится код. Я действительно понятия не имею, как выразить это в формуле.
Я обнаружил, что подход Artefacto к сортировке строк увеличивает производительность. Добавление
перед
array_reduce
значительно повысит производительность.Также обратите внимание, что это вернет самую длинную совпадающую начальную подстроку , которая более универсальна, но не даст вам общего пути . Ты должен бежать
по результату. И затем вы можете использовать результат для удаления значений
который должен дать:
Обратная связь приветствуется.
источник
Вы можете удалить префикс самым быстрым способом, прочитав каждый символ только один раз:
источник
Преимущество этого заключается в отсутствии линейной временной сложности; однако в большинстве случаев сортировка определенно не займет больше времени.
По сути, умная часть (по крайней мере, я не мог найти в ней недостатка) заключается в том, что после сортировки вам нужно будет только сравнить первый путь с последним.
источник
ИЗМЕНИТЬ Вариант моего исходного метода с использованием array_walk для восстановления массива
РЕДАКТИРОВАТЬ
Наиболее эффективный и элегантный ответ, вероятно, будет включать использование функций и методов из каждого из предоставленных ответов.
источник
Я бы
explode
использовал значения на основе /, а затем использовал быarray_intersect_assoc
для обнаружения общих элементов и обеспечения того, чтобы они имели правильный соответствующий индекс в массиве. Результирующий массив может быть повторно объединен для создания общего пути.Это не проверено, но идея состоит в том, что
$commonPath
массив всегда содержит только элементы пути, которые содержались во всех массивах путей, которые сравнивались с ним. Когда цикл завершен, мы просто рекомбинируем его с помощью /, чтобы получить истинное значение.$commonPath
Обновление Как указал Феликс Клинг,
array_intersect
не будут рассматривать пути, которые имеют общие элементы, но в разном порядке ... Чтобы решить эту проблему, я использовалarray_intersect_assoc
вместоarray_intersect
Обновление Добавлен код для удаления общего пути (или тетриса!) Из массива.
источник
/a/b/c/d
и/d/c/b/a
. Те же элементы, разные пути.Проблему можно упростить, если просто взглянуть на нее под углом сравнения строк. Вероятно, это быстрее, чем разделение массива:
источник
Возможно, портирование алгоритма,
os.path.commonprefix(m)
используемого Python, сработает?Это эээ ... что-то вроде
После этого вы можете просто подставить каждый элемент исходного списка с длиной общего префикса в качестве начального смещения.
источник
Я брошу шляпу на ринг ...
Использование:
источник
Что ж, здесь уже есть некоторые решения, но просто потому, что это было весело:
Вывод:
источник
Это отлично работает ... похоже на Mark Baker, но использует str_replace
источник
Наверное, слишком наивно и глупо, но это работает. Я использовал такой алгоритм :
Вывод:
:)
источник
/www/htdocs/1/sites/conf/
найден как общее совпадение. Кроме того, алгоритм ищет подстроки, начинающиеся где угодно в строке, но вы знаете, что в этом вопросе вы можете начать с местоположения 0, что значительно упрощает задачу.