0Pricing
Lua Academy · Урок

map, filter, reduce

Создавайте функции высшего порядка.

«map, filter, reduce» — бесплатный урок Lua Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.

Большая тройка

Отображение, фильтрация и свёртка — основные инструменты функциональной обработки списков. Каждый из них принимает список и функцию и возвращает результат, не заставляя Вас вручную писать цикл.

В Lua они не входят в стандартный набор, но их легко написать, и на них хорошо видно, как работают функции высшего порядка.

Отображение: преобразование каждого элемента

Отображение применяет функцию к каждому элементу и собирает результаты в новый список. Исходный список остаётся неизменным.

Переданная Вами функция определяет преобразование, поэтому одна функция map может удваивать числа, возводить их в квадрат или выполнять любое изменение отдельных элементов.

local function map(t, f)
  local out = {}
  for i, v in ipairs(t) do
    out[i] = f(v)
  end
  return out
end

local r = map({1, 2, 3}, function(x) return x * x end)
print(table.concat(r, ", "))

Отображение сохраняет длину

Отображение всегда возвращает список с тем же количеством элементов, что и входной список. Каждому входному элементу соответствует ровно один выходной элемент.

Если нужно удалить элементы, это задача фильтрации, а не отображения.

local function map(t, f)
  local out = {}
  for i, v in ipairs(t) do out[i] = f(v) end
  return out
end

local names = {"ada", "lin", "sam"}
local caps = map(names, string.upper)
print(table.concat(caps, " "))
print(#caps)

Фильтрация: сохранение выбранных элементов

Фильтрация сохраняет только те элементы, для которых условие возвращает истинное значение. Условие — это функция, возвращающая логическое значение.

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

local function filter(t, pred)
  local out = {}
  for _, v in ipairs(t) do
    if pred(v) then out[#out + 1] = v end
  end
  return out
end

local evens = filter({1,2,3,4,5,6}, function(x) return x % 2 == 0 end)
print(table.concat(evens, ", "))

Фильтрация сохраняет порядок

Фильтрация проходит по списку по порядку и добавляет каждый сохранённый элемент, поэтому оставшиеся элементы сохраняют исходную последовательность.

Использование #out + 1 в качестве индекса сохраняет в результате массив без пропусков, который Lua рассматривает как правильную последовательность.

local function filter(t, pred)
  local out = {}
  for _, v in ipairs(t) do
    if pred(v) then out[#out + 1] = v end
  end
  return out
end

local long = filter({"hi", "hello", "yo", "howdy"},
  function(s) return #s > 2 end)
print(table.concat(long, ", "))

Свёртка: объединение в одно значение

Свёртка, которую также называют свёртыванием, превращает список в одно значение. Она хранит накопитель и объединяет его с каждым элементом с помощью Вашей функции.

Вы задаёте начальное значение и функцию объединения, а свёртка последовательно передаёт накопитель через все элементы.

local function reduce(t, f, acc)
  for _, v in ipairs(t) do
    acc = f(acc, v)
  end
  return acc
end

local sum = reduce({1,2,3,4}, function(a, x) return a + x end, 0)
print(sum)

Свёртка универсальна

Изменяя функцию объединения и начальное значение, с помощью свёртки можно складывать и умножать значения, находить максимум или создавать строку.

Здесь накопитель начинается со значения 1 и умножается, образуя произведение в стиле факториала.

local function reduce(t, f, acc)
  for _, v in ipairs(t) do acc = f(acc, v) end
  return acc
end

local product = reduce({1,2,3,4,5}, function(a, x) return a * x end, 1)
print(product)

Поиск максимума с помощью свёртки

Свёртка подходит не только для арифметики. Функция объединения может сравнивать значения и на каждом шаге сохранять большее.

Если начать накопитель с первого элемента или с очень маленького числа, свёртка аккуратно найдёт максимум.

local function reduce(t, f, acc)
  for _, v in ipairs(t) do acc = f(acc, v) end
  return acc
end

local max = reduce({3, 8, 2, 11, 6},
  function(a, x) if x > a then return x else return a end end, -math.huge)
print(max)

Объединение операций в цепочку

Настоящая сила проявляется, когда Вы объединяете все три операции в цепочку. Фильтрация сужает набор данных, отображение преобразует его, а свёртка обобщает результат.

Каждый этап представляет собой небольшой понятный шаг, а вместе они заменяют запутанный ручной цикл.

local function filter(t, p) local o={} for _,v in ipairs(t) do if p(v) then o[#o+1]=v end end return o end
local function map(t, f) local o={} for i,v in ipairs(t) do o[i]=f(v) end return o end
local function reduce(t, f, a) for _,v in ipairs(t) do a=f(a,v) end return a end

local nums = {1,2,3,4,5,6}
local r = reduce(map(filter(nums, function(x) return x%2==0 end),
  function(x) return x*x end), function(a,x) return a+x end, 0)
print(r)

Исходные данные в безопасности

Отображение и фильтрация всегда создают новые таблицы и никогда не изменяют входные данные. Благодаря этому конвейеры обработки данных предсказуемы: исходные данные остаются доступными после каждого этапа.

Свёртка также не изменяет список, а возвращает только объединённый результат.

Подходит для любого списка

Поскольку функция является параметром, эти инструменты работают с любыми данными. Одна и та же функция map может переводить строки в верхний регистр, пересчитывать цены или форматировать записи.

Именно поэтому функции первого класса так полезны: цикл пишется один раз, а затем ему передаются разные функции.

local function map(t, f) local o={} for i,v in ipairs(t) do o[i]=f(v) end return o end

local prices = {10, 20, 30}
local withTax = map(prices, function(p) return p * 1.18 end)
print(table.concat(withTax, ", "))

Быстрая проверка

Подумайте, как эти операции влияют на длину списка.

Повторение

Отображение преобразует каждый элемент и сохраняет длину, фильтрация сохраняет элементы, соответствующие условию, а свёртка объединяет список в одно значение с помощью накопителя.

Объединение фильтрации, отображения и свёртки в цепочку создаёт понятные конвейеры обработки данных без ручных циклов, а исходные таблицы остаются неизменными.

Часто задаваемые вопросы

Урок «map, filter, reduce» бесплатный?

Да — полный текст урока «map, filter, reduce» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.

Чему я научусь в уроке «map, filter, reduce»?

Создавайте функции высшего порядка. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Lua Academy?

Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «map, filter, reduce»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Lua Academy?

Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Функции как значения
  2. map, filter, reduce
  3. Частичное применение
  4. Композиция функций
← Назад к Lua Academy