0Pricing
Lua Academy · レッスン

map、filter、reduce

高階関数のヘルパーを構築します。

「map、filter、reduce」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

3つの基本操作

map、filter、reduceは、関数型のリスト処理における基本的なツールです。それぞれリストと関数を受け取り、ループを手動で記述することなく結果を返します。

Luaにはこれらが組み込みで用意されていませんが、短いコードで作成でき、高階関数の仕組みを理解するのに役立ちます。

Map:各要素を変換する

mapはすべての要素に関数を適用し、その結果を新しいリストに集めます。元のリストは変更されません。

渡す関数によって変換内容を決められるため、1つの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, ", "))

Mapは長さを維持する

mapは常に、入力と同じ数の要素を持つリストを返します。すべての要素が、ちょうど1つの出力要素に対応します。

要素を取り除く必要がある場合は、mapではなくfilterを使います。

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)

Filter:一部の要素を残す

filterは、述語がtrueを返す要素だけを残します。述語とは、boolean値を返す関数です。

結果は元のリストより短くなる場合がありますが、長くなることはありません。

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

Filterは順序を維持する

filterはリストを順番に走査し、残す各要素を追加するため、残った要素は元の順序を保ちます。

インデックスに#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, ", "))

Reduce:1つにまとめる

reduceはfoldとも呼ばれ、リストを1つの値に集約します。アキュムレーターを保持し、指定した関数を使って各要素と組み合わせます。

開始値と結合関数を指定すると、reduceがすべての要素に対してアキュムレーターを順番に渡していきます。

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)

Reduceは柔軟に使える

結合関数と開始値を変えることで、reduceは合計、積、最大値の計算や、文字列の構築に使えます。

ここではアキュムレーターを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)

Reduceで最大値を求める

reduceは算術演算だけに限られません。結合関数で値を比較し、各段階で大きい方を残すこともできます。

アキュムレーターを最初の要素、または非常に小さい数値から始めると、reduceで最大値を簡潔に求められます。

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)

3つを連結して使う

3つを連結すると、本当の力を発揮します。filterでデータを絞り込み、mapで変換し、reduceで要約します。

各段階が小さく明確な処理になるため、組み合わせることで複雑な手動ループを置き換えられます。

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とfilterは常に新しいテーブルを作成し、入力を変更しません。そのため、各段階の後でも前のデータを利用でき、パイプラインを予測しやすくなります。

reduceもリストを変更せず、結合した結果だけを返します。

どのリストにも使える汎用性

関数をパラメーターとして渡すため、これらのツールはどのようなデータにも使えます。同じ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はアキュムレーターを使ってリストを1つの値に集約します。

filter、map、reduceを連結すると、手動ループなしで明確なデータ処理パイプラインを構築できます。また、元のテーブルは変更されません。

よくある質問

「map、filter、reduce」レッスンは無料ですか?

はい。「map、filter、reduce」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「map、filter、reduce」で何を学びますか?

高階関数のヘルパーを構築します。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応の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に戻る