Enum
ชุดของ algorithm สำหรับใช้งานกับ Enum
Enum
module Enum
มีมากกว่า 70 function ให้ใช้งาน ที่น่าสนใจคือ colllection ทั้งหมดนอกจาก tuple ที่เราได้เรียนกันมาใน บทที่แล้ว ล้วนแล้วแต่เป็น Enum
บทนี้จะครอบคลุมเพียงแค่ function บางส่วน แต่คุณก็สามารถไปศึกษาเพิ่มได้เอง เอาล่ะ มาทำลองเล่นใน IEx กันสักหน่อยดีกว่า
iex> Enum.__info__(:functions) |> Enum.each(fn({function, arity}) ->
...> IO.puts "#{function}/#{arity}"
...> end)
all?/1
all?/2
any?/1
any?/2
at/2
at/3
...
จากที่ลองจะเห็นว่ามี function มากมายให้เราใช้งานจริง ๆ Enum
นับเป็น core ของการเขียนโปรแกรมแบบ functional แล้วมันก็มีประโยชน์มาก ๆ เลยทีเดียว
หากเราใช้มันร่วมกับสิ่งเยี่ยมยอดอื่น ๆ ของ Elixir มันจะทำให้ developer ทำงานได้อย่างมีประสิทธิภาพมากเลยทีเดียว
สำหรับรายชื่อ function ทั้งหมด สามารถเข้าไปอ่านเพิ่มได้ที่ Enum
สำหรับ lazy enumeration ใช้โมดูล Stream
.
all?
เมื่อเราใช้ all?/2
กับ Enum
จำนวนมาก เราสามารถใช้งาน function กับ item ทั้งหมดของ collection ได้ โดยจะตอบ true
เมื่อ item ใน collection ทั้งหมดเป็น true
นอกจากนั้นจะเป็น false
iex> Enum.all?(["foo", "bar", "hello"], fn(s) -> String.length(s) == 3 end)
false
iex> Enum.all?(["foo", "bar", "hello"], fn(s) -> String.length(s) > 1 end)
true
any?
any?/2
จะคืนค่า true
ถ้ามีตัวใดตัวนึงใน collection เป็น true
iex> Enum.any?(["foo", "bar", "hello"], fn(s) -> String.length(s) == 5 end)
true
chunk_every
ถ้าคุณต้องการแบ่ง collection เป็นกลุ่มเล็ก ๆ chunk_every/2
เป็น function ที่คุณกำลังตามหา
iex> Enum.chunk_every([1, 2, 3, 4, 5, 6], 2)
[[1, 2], [3, 4], [5, 6]]
มีตัวเลือกเล็กน้อยสำหรับ chunk_every/4
แต่เราจะไม่พูดถึงมันตรงนี้ ดูเพิ่มเติมที่ the official documentation of this function
chunk_by
ถ้าเราต้องการจับกลุ่ม collection ของเราด้วยค่าอื่นนอกเหนือจาก size ของมัน เราสามารถใช้ function chunk_by/2
ได้. มันรับ enumerable และ function เข้าไป และคืนค่าเมื่อ function สร้างกลุ่มใหม่ แล้วเริ่มทำกับตัวต่อไป
iex> Enum.chunk_by(["one", "two", "three", "four", "five"], fn(x) -> String.length(x) end)
[["one", "two"], ["three"], ["four", "five"]]
iex> Enum.chunk_by(["one", "two", "three", "four", "five", "six"], fn(x) -> String.length(x) end)
[["one", "two"], ["three"], ["four", "five"], ["six"]]
map_every
บางครั้งการดึงค่าเป็นก้อน ๆ จาก collection ไม่เพียงพอกับสิ่งที่เราต้องการ ในสถานการณ์นี้ map_every/3
มีประโยชน์มากในการเข้าถึง item ทุก ๆ nth
ครั้ง เริ่มโดยเข้าถึงตัวแรกสุดก่อน
# ใช้ function ทุก ๆ 3 ค่า
iex> Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8], 3, fn x -> x + 1000 end)
[1001, 2, 3, 1004, 5, 6, 1007, 8]
each
มันอาจจะจำเป็นที่จะใช้ค่าแต่ละตัวใน collection โดยไม่สร้างค่าใหม่ สำหรับสถานการณ์นี้เราสามารถใช้ each/2
ได้
iex> Enum.each(["one", "two", "three"], fn(s) -> IO.puts(s) end)
one
two
three
:ok
หมายเหตุ: function each/2
จะคืนค่า atom :ok
map
เราสามารถใช้ function กับแต่ละ item เพื่อสร้างเป็น collection ใหม่ได้ด้วย function map/2
iex> Enum.map([0, 1, 2, 3], fn(x) -> x - 1 end)
[-1, 0, 1, 2]
min
min/1
หาค่าน้อยที่สุดใน collection
iex> Enum.min([5, 3, 0, -1])
-1
min/2
ทำเหมือนกัน แต่ถ้า enumerable เป็นค่าว่างมันจะคืนค่าของ function ที่เราใส่เข้าไปแทน
iex> Enum.min([], fn -> :foo end)
:foo
max
max/1
คืนค่ามากที่สุดของ collection:
iex> Enum.max([5, 3, 0, -1])
5
max/2
กลายเป็น max/1
ถ้า enumerable มีค่า เช่นเดียวกันกับ min/2
ที่จะกลายเป็น min/1
:
Enum.max([], fn -> :bar end)
:bar
reduce
ด้วย function reduce/3
ทำให้เราสามารถรวบ collection ให้เหลือเพียงค่าเดียวได้ การที่จะรวบ collection เราสามารถส่ง accumulator (10
ในตัวอย่างด้านล่างนี้) เข้าไปใน function ถ้าไม่ได้กำหนด accumulator มันจะใช้ตัวแรกเป็น accumulator แทน
iex> Enum.reduce([1, 2, 3], 10, fn(x, acc) -> x + acc end)
16
iex> Enum.reduce([1, 2, 3], fn(x, acc) -> x + acc end)
6
iex> Enum.reduce(["a","b","c"], "1", fn(x,acc)-> x <> acc end)
"cba1"
sort
การ sort collection สามารถทำได้ง่ายนิดเดียวด้วย 2 function ที่ Elixir มีไว้ให้ใช้
sort/1
ใช้ term ของ Erlang ในการจัดลำดับ
uses Erlang’s term ordering to determine the sorted order:
iex> Enum.sort([5, 6, 1, 3, -1, 4])
[-1, 1, 3, 4, 5, 6]
iex> Enum.sort([:foo, "bar", Enum, -1, 4])
[-1, 4, Enum, :foo, "bar"]
เราสามารถใช้ sort function ที่เราสร้างขึ้นมาเองได้ใน sort/2
# ใช้ function
iex> Enum.sort([%{:val => 4}, %{:val => 1}], fn(x, y) -> x[:val] > y[:val] end)
[%{val: 4}, %{val: 1}]
# โดยไม่ใช้ function
iex> Enum.sort([%{:count => 4}, %{:count => 1}])
[%{count: 1}, %{count: 4}]
uniq_by
เราสามารถใช้ uniq_by/2
เพื่อลบค่าซ้ำใน enumerables ได้:
iex> Enum.uniq_by([1, 2, 3, 2, 1, 1, 1, 1, 1], fn x -> x end)
[1, 2, 3]
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!