Что делает groupBy, partition, sliding?

В Scala методы groupBy, partition и sliding применяются к коллекциям и используются для их трансформации и анализа. Каждый из них выполняет уникальную задачу при работе с последовательностями, и все они являются частью обширного API коллекций.

groupBy

Метод groupBy разбивает коллекцию на группы по какому-то признаку. Возвращает Map[K, List[V]], где ключ K — результат применения функции группировки, а значение List[V] — элементы, соответствующие этому ключу.

Сигнатура:

def groupBy\[K\](f: A => K): Map\[K, List\[A\]\]

Пример:

val names = List("Alice", "Bob", "Anna", "Charlie")
val grouped = names.groupBy(\_.head)

Результат:

Map(
'A' -> List("Alice", "Anna"),
'B' -> List("Bob"),
'C' -> List("Charlie")
)

Применение:

  • Группировка по первой букве, длине, категории.

  • Построение индексов.

  • Подготовка данных к агрегированию.

partition

Метод partition делит коллекцию на две по предикату. Возвращает кортеж из двух коллекций: первая содержит элементы, для которых предикат вернул true, вторая — для которых false.

Сигнатура:

def partition(p: A => Boolean): (List\[A\], List\[A\])

Пример:

val nums = List(1, 2, 3, 4, 5)
val (even, odd) = nums.partition(_ % 2 == 0)

Результат:

even: List(2, 4)
odd: List(1, 3, 5)

Применение:

  • Разделение элементов на подходящие и непригодные.

  • Фильтрация с сохранением отброшенных.

  • Валидация входных данных.

sliding

Метод sliding возвращает итератор по скользящим окнам фиксированного размера. Может использоваться с шагом.

Сигнатура:

def sliding(size: Int): Iterator\[List\[A\]\]
def sliding(size: Int, step: Int): Iterator\[List\[A\]\]

Пример 1: без шага (step = 1)

val nums = List(1, 2, 3, 4, 5)
nums.sliding(3).toList

Результат:

List(List(1, 2, 3), List(2, 3, 4), List(3, 4, 5))

Пример 2: с шагом 2

nums.sliding(2, 2).toList

Результат:

List(List(1, 2), List(3, 4), List(5))

Применение:

  • Вычисление скользящих средних, максимумов, сумм.

  • Обработка временных рядов.

  • Поиск паттернов в потоках данных.

  • Разбиение коллекции на блоки фиксированной длины.

Сравнение по назначению:

Метод Возвращает Для чего нужен
groupBy Map[K, List[A]] Группировка по ключу
--- --- ---
partition (List[A], List[A]) Разделение на две части по условию
--- --- ---
sliding Iterator[List[A]] Последовательные блоки (окна)
--- --- ---

Пример совместного использования:

val data = List(10, 20, 30, 15, 25, 35)
val grouped = data.groupBy(_ / 10) // Map(1 -> List(10,15), 2 -> List(20,25), 3 -> List(30,35))
val (gt20, lte20) = data.partition(_ > 20) // gt20: List(30,25,35), lte20: List(10,20,15)
val windows = data.sliding(3).toList // List(List(10,20,30), List(20,30,15), ...)

Особенности:

  • groupBy создает все группы одновременно, и результат помещается в память — может быть дорого при большом числе групп.

  • partition выполняет один проход по данным, эффективно.

  • sliding возвращает итератор, что позволяет работать с бесконечными потоками или огромными коллекциями без загрузки в память сразу.