Lua Academy · 课时

map、filter、reduce

构建高阶辅助函数。

第 2 / 4 课13 个步骤

map、filter、reduce 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 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)

过滤:保留部分元素

过滤只保留谓词返回 true 的元素。谓词是一个返回布尔值的函数。

结果是一个可能比原列表短、但绝不会更长的新列表。

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, ", "))

快速检查

思考这些操作会如何影响列表长度。

回顾

映射会转换每个元素并保持长度不变,过滤会保留通过谓词的元素,归约则会使用累加器将列表折叠为一个值。

串联过滤、映射和归约,可以在无需手写循环的情况下构建清晰的数据处理流水线,而且原始表保持不变。

免费开始

用 AI 导师学习 Lua — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
40
课程
159

常见问题解答

「map、filter、reduce」课时是免费的吗?

是的 — 「map、filter、reduce」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「map、filter、reduce」这节课中我会学到什么?

构建高阶辅助函数。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「map、filter、reduce」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Lua Academy 课中编写并运行代码吗?

能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 作为值的函数
  2. map、filter、reduce
  3. 部分应用
  4. 组合函数
← 返回 Lua Academy