5. Начните работу с фильтрами

В этом задании вы немного узнаете о фильтрах в Kotlin. Фильтры — это удобный способ получить часть списка на основе определенного условия.

  1. В файле Hello.kt определите список декораций для аквариума на верхнем уровне с помощью listOf(). Вы можете заменить содержимое файла Hello.kt .
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
  1. Создайте новую main()функцию со строкой кода для вывода только тех декораций, которые начинаются с буквы «p». Код условия фильтрации заключен в фигурные скобки {}и itнеявно ссылается на каждый элемент по мере того, как фильтр проходит по списку. Если выражение возвращает true true, элемент включается в список.
fun main() {
    println( decorations.filter {it[0] == 'p'})
}
  1. Запустите программу, и в окне «Выполнить» вы увидите следующий вывод :
⇒ [pagoda, plastic plant]

Если вы знакомы с фильтрами в других языках, вас может заинтересовать вопрос, являются ли фильтры в Kotlin «жадными» или «ленивыми» . Создается ли список результатов немедленно (жадный) или при обращении к нему (ленивый)? В Kotlin это происходит так, как вам нужно. По умолчанию filterиспользуется жадный фильтр, и каждый раз при использовании фильтра создается список.

Чтобы сделать фильтр ленивым, можно использовать Sequenceколлекцию, которая может просматривать только один элемент за раз, начиная с начала и заканчивая концом. Удобно, что это именно тот API, который нужен ленивому фильтру.

  1. В файле Hello.kt измените свой код так, чтобы отфильтрованный список был присвоен переменной с именем eager, а затем выведите её на экран.
fun main() {
    val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

    // eager, creates a new list
    val eager = decorations.filter { it [0] == 'p' }
    println("eager: $eager")
  1. Ниже приведен код, который оценивает фильтр, используя оператор ` Sequencewith` asSequence(). Присвойте полученную последовательность переменной с именем ` filtered` и распечатайте ее.
   // lazy, will wait until asked to evaluate
    val filtered = decorations.asSequence().filter { it[0] == 'p' }
    println("filtered: $filtered")

Когда вы возвращаете результаты фильтрации в виде списка Sequence, filteredпеременная не будет содержать новый список — она будет содержать список Sequenceэлементов и информацию о фильтре, который нужно применить к этим элементам. При каждом обращении к элементам списка Sequenceприменяется фильтр, и результат возвращается вам.

  1. Принудительное вычисление последовательности путем ее преобразования в объект Listс помощью оператора toList()`.`. Вывести результат.
    // force evaluation of the lazy list
    val newList = filtered.toList()
    println("new list: $newList")
  1. Запустите свою программу и посмотрите на результат.
⇒ eager: [pagoda, plastic plant]
filtered: kotlin.sequences.FilteringSequence@386cc1c4
new list: [pagoda, plastic plant]

Для визуализации происходящего с Sequenceленивой оценкой используйте map()функцию. Эта map()функция выполняет простое преобразование каждого элемента в последовательности.

  1. Используя тот же decorationsсписок, что и выше, выполните преобразование, которое map()ничего не делает и просто возвращает переданный элемент. Добавьте индикатор, println()который будет отображаться каждый раз при обращении к элементу, и присвойте последовательность переменной с именем lazyMap.
    val lazyMap = decorations.asSequence().map {
        println("access: $it")
        it
    }
  1. Выведите на экран lazyMapпервый элемент , lazyMapиспользуя оператор print first(), и выведите lazyMapпреобразованный в List.
    println("lazy: $lazyMap")
    println("-----")
    println("first: ${lazyMap.first()}")
    println("-----")
    println("all: ${lazyMap.toList()}")
  1. Запустите свою программу и понаблюдайте за выводом. При выводе на экран lazyMapпросто печатается ссылка на элемент Sequence— внутренний метод println()не вызывается. При выводе первого элемента осуществляется доступ только к первому элементу. Преобразование элемента Sequenceв другой тип данных Listобеспечивает доступ ко всем элементам.
⇒ lazy: kotlin.sequences.TransformingSequence@5ba23b66
-----
access: rock
first: rock
-----
access: rock
access: pagoda
access: plastic plant
access: alligator
access: flowerpot
all: [rock, pagoda, plastic plant, alligator, flowerpot]
  1. Создайте новый фильтр Sequence, используя исходный фильтр, прежде чем применять его map. Распечатайте полученный результат.
    val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
        println("access: $it")
        it
    }
    println("-----")
    println("filtered: ${lazyMap2.toList()}")
  1. Запустите программу и понаблюдайте за дополнительным выводом. Как и в случае с получением первого элемента, внутренний метод println()вызывается только для тех элементов, к которым осуществляется доступ.
⇒
-----
access: pagoda
access: plastic plant
filtered: [pagoda, plastic plant]
  1. Ещё одна полезная функция преобразования коллекций в Kotlin — это flatten(). Эта функция создаёт список из коллекции коллекций, например, массива массивов или списка списков.
  2. Создайте список списков. Затем примените функцию flatten() для преобразования всех списков в один список. Выведите результат.
val mysports = listOf("basketball", "fishing", "running")
val myplayers = listOf("LeBron James", "Ernest Hemingway", "Usain Bolt")
val mycities = listOf("Los Angeles", "Chicago", "Jamaica")
val mylist = listOf(mysports, myplayers, mycities)     // list of lists
println("-----")
println("Flat: ${mylist.flatten()}")
⇒
-----
Flat: [basketball, fishing, running, LeBron James, Ernest Hemingway, Usain Bolt, Los Angeles, Chicago, Jamaica]

Последнее изменение: Воскресенье, 5 апреля 2026, 12:29