Разделите имя файла на абсолютные пути в Scala

#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 $.html

5. Обратите внимание, что если путь еще не из корня файловой системы, вы можете захотеть .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