Можно ли при выполнении операции коллекций изменить базовую коллекцию? - PullRequest
0 голосов
/ 06 мая 2020

Например, у меня есть следующий код для рекурсивного копирования содержимого каталога.

    private fun copyContentDirectory(directory : File): List<File> {
        val files = directory.listFiles().toList()
        val filesToTransform = mutableListOf<File>()

        // Add each file + directory. Then, recursively add the files in each directory.
        files
                .onEach  { filesToTransform += it }
                .filter  { it.isDirectory }
                .forEach { filesToTransform += copyContentDirectory(it) }

        return filesToTransform
    }

Возможно ли что-то вроде следующего? Если нет, то почему?


    private fun copyContentDirectory(directory : File): List<File> {
        return directory.listFiles().toList()
                .filter  { it.isDirectory }
                .onEach  { <thisList> += copyContentDirectory(it) }
    }

Где thisList - некоторый символ, который позволяет мне ссылаться на базовый список. Такое существует?

1 Ответ

1 голос
/ 06 мая 2020

Согласно комментариям, ваши намерения не очень ясны.

Глядя на второй пример, кажется очевидным ответом заменить эту строку:

.onEach { <thisList> += copyContentDirectory(it) }

на одну используя flatMap(), например:

.flatMap{ copyContentDirectory(it) }

Это собирает вместе результаты всех рекурсивных вызовов и возвращает их в виде единого списка - что, я думаю, вам и нужно.

Однако это только выявляет более глубокие проблемы:

  • Несмотря на название, метод на самом деле ничего не копирует, а просто собирает список.
  • Список будет всегда быть пустым - он рекурсивно просматривает каталоги, но никогда не возвращает никаких файлов, поэтому только каждый будет объединять пустые списки.

Вот версия, которая решает вторую проблему. Я также переименовал его, переделал как функцию расширения и использовал partition(), чтобы избежать двойной фильтрации. (Первый результат - это те файлы, которые соответствуют предикату, то есть каталоги, по которым он рекурсивно проходит; второй - это файлы, не соответствующие предикату, то есть не каталоги, которые он включает напрямую.) И потому что listFiles() может возвращать null в некоторых случаях, он также должен справиться с этим.

private fun File.listContents(): List<File>
    = listFiles()
        ?.partition{ it.isDirectory }
        ?.let{ it.first.flatMap{ it.listContents() } + it.second }
        ?: listOf()

(Это не касается копирования, но вопрос не указывает, как вы планируете подойти к этому.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...