filter, filterNot и partition
Разделяйте и выбирайте элементы с помощью функций на основе предикатов.
«filter, filterNot и partition» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Операции выбора
filter оставляет элементы, соответствующие предикату. filterNot оставляет элементы, которые ему НЕ соответствуют. Разбиение за один раз разделяет коллекцию на два списка.
Базовое применение filter
filter { ... } возвращает новый список, содержащий только элементы, для которых предикат имеет значение true.
fun main() {
val nums = listOf(1, 2, 3, 4, 5, 6)
val evens = nums.filter { it % 2 == 0 }
println(evens) // [2, 4, 6]
}filterNot
filterNot { ... } — обратная операция: оставляет элементы, для которых предикат имеет значение false. Результат такой же, как при инверсии предиката, но намерение выражено яснее.
fun main() {
val nums = listOf(1, 2, 3, 4, 5, 6)
val odds = nums.filterNot { it % 2 == 0 }
println(odds) // [1, 3, 5]
}Разбиение
partition возвращает Pair: сначала идут соответствующие элементы, затем несоответствующие. Это позволяет избежать двух проходов по данным.
fun main() {
val nums = listOf(1, 2, 3, 4, 5, 6)
val (evens, odds) = nums.partition { it % 2 == 0 }
println("evens=$evens odds=$odds")
}Разбиение с классом данных
Разделяйте список записей на две группы за один проход.
data class User(val name: String, val active: Boolean)
fun main() {
val users = listOf(User("Ada", true), User("Ben", false), User("Cal", true))
val (active, inactive) = users.partition { it.active }
println("active=${active.map { it.name }}")
println("inactive=${inactive.map { it.name }}")
}filterIndexed
Предикат получает и индекс, и значение — это полезно, когда важна позиция.
fun main() {
val nums = listOf(10, 20, 30, 40, 50)
val every2nd = nums.filterIndexed { i, _ -> i % 2 == 0 }
println(every2nd) // [10, 30, 50]
}filterIsInstance
Оставляйте только элементы определённого типа — внутри выполняется интеллектуальное приведение типов.
fun main() {
val mixed: List<Any> = listOf(1, "hello", 2.0, "world", 3)
val onlyStrings = mixed.filterIsInstance<String>()
println(onlyStrings) // [hello, world]
}filterNotNull
Удаляйте значения null из списка допускающих null элементов — результатом будет список ненулевых элементов.
fun main() {
val mixed: List<String?> = listOf("a", null, "b", null, "c")
val nonNull = mixed.filterNotNull()
println(nonNull) // [a, b, c]
}Цепочка filter и map
Объединяйте filter и map в конвейерах выбора и преобразования.
data class Product(val name: String, val price: Double, val inStock: Boolean)
fun main() {
val products = listOf(
Product("Pen", 1.0, true),
Product("Book", 12.0, false),
Product("Lamp", 25.0, true)
)
val availableNames = products.filter { it.inStock }.map { it.name }
println(availableNames) // [Pen, Lamp]
}Отрицание с помощью filterNot для ясности
Иногда filterNot { it.isActive } читается лучше, чем filter { !it.isActive }.
data class Task(val title: String, val done: Boolean)
fun main() {
val tasks = listOf(Task("Email", true), Task("Lunch", false), Task("Code", true))
val pending = tasks.filterNot { it.done }
println(pending) // [Task(title=Lunch, done=false)]
}Разбиение возвращает списки
Pair из partition содержит два обычных списка — разберите их или обратитесь к ним через .first / .second.
fun main() {
val nums = (1..10).toList()
val result = nums.partition { it > 5 }
println("above 5: ${result.first}")
println("below 6: ${result.second}")
}Разбиение и два вызова filter
Если нужны оба подмножества, partition работает быстрее: выполняется один проход вместо двух.
fun main() {
val nums = (1..10).toList()
// Two passes:
val a = nums.filter { it > 5 }
val b = nums.filter { it <= 5 }
// One pass:
val (c, d) = nums.partition { it > 5 }
println("$a $b")
println("$c $d")
}Быстрая проверка
Какая функция за один проход возвращает BOTH соответствующие и несоответствующие элементы?
Повторение
filter выбирает соответствующие элементы; filterNot — несоответствующие; разбиение за один проход возвращает обе группы. Используйте filterIsInstance, чтобы оставить элементы определённого типа, и filterNotNull, чтобы удалить значения null. Объединяйте их с map для выбора и преобразования.
Часто задаваемые вопросы
Урок «filter, filterNot и partition» бесплатный?
Да — полный текст урока «filter, filterNot и partition» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «filter, filterNot и partition»?
Разделяйте и выбирайте элементы с помощью функций на основе предикатов. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «filter, filterNot и partition»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- map и flatMap: преобразование каждого элемента
- filter, filterNot и partition
- fold, reduce и runningFold
- Цепочки конвейеров и отказ от промежуточных списков с Sequence