#scala #path #split
#scala #путь #разделить
Вопрос:
Учитывая строку
val path = "/what/an/awesome/path"
как я могу использовать Scala для создания списка абсолютных путей для каждого каталога в path?
Результат должен быть:
List(/what, /what/an, /what/an/awesome, /what/an/awesome/path)
Бонусные баллы за элегантное, функциональное решение.
Комментарии:
1. Я действительно поражен всеми высококачественными ответами. Я хотел бы принять более одного ответа, но поскольку это невозможно, я приму первый правильный. Спасибо за вашу поддержку.
Ответ №1:
val path = "/what/an/awesome/path"
val file = new java.io.File(path)
val prefixes = Iterator.iterate(file)(_.getParentFile).takeWhile(_ != null).toList.reverse
Комментарии:
1. Я никогда раньше не видел этого метода. Не могли бы вы сказать мне, правильно ли я понял? После каждой итерации возвращаемый объект
.getParentFile
становится «новым»file
?2. Неплохо. 1. Это дает корневой каталог в качестве первого элемента, хотя?
3. @huynhjl Добавление
.drop(1)
исправляет это достаточно легко 🙂4. @Tempus да, это так
Iterator.iterate(startingValue)(functionToDeriveNext)
. Существует ряд аналогичных фабричных методов для компаньонов для различных типов коллекций.Iterator.continually
например, тоже интересно. scala-lang.org/api/rc/scala/collection/Iterator $.html5. Обратите внимание, что если путь еще не из корня файловой системы, вы можете захотеть
.getCanonicalPath
использовать его.
Ответ №2:
val path = "/what/an/awesome/path"
scala> path.tail.split("/").scanLeft(""){_ "/" _}.tail.toList
res1: List[java.lang.String] = List(/what, /what/an, /what/an/awesome, /what/an/awesome/path)
Ответ №3:
Используя новую библиотеку ввода-вывода Scala от Джесси Эйчара (версия 0.2.0), похоже, вы можете сделать что-то вроде этого:
val path = Path("/what/an/awesome/path")
val paths = (path :: path.parents).reverse
Возможно, вы захотите преобразовать объекты Path в результирующем списке в строки, но, возможно, было бы безопаснее и полезнее оставить их как объекты Path.
Эта библиотека, насколько я знаю, рассматривается для включения в дистрибутив Scala.
Ответ №4:
path.drop(1).split("/").foldLeft(List.empty[String])((list, string) => ((list.headOption.getOrElse("") "/" string) :: list)).reverse.toList
Вероятно, есть более чистый способ с использованием scanLeft, но я не смог его понять
Комментарии:
1. Вероятно, вокруг этих строк
path.split("/").drop(1).scanLeft("")((s,elem) => s "/" elem).drop(1)
Ответ №5:
Метод регулярных выражений с необычными штанами:
val R = "(/.*)/".r
(path '/').inits.collect{case R(x) => x}.toList