Elixir - จำนวนนับ
แจงนับเป็นวัตถุที่สามารถแจกแจงได้ "แจกแจง" หมายถึงการนับจำนวนสมาชิกของชุด / คอลเลกชัน / หมวดหมู่ทีละคน (โดยปกติจะเรียงตามชื่อ)
Elixir ให้แนวคิดเกี่ยวกับการแจงนับและโมดูล Enumเพื่อใช้งานได้ ฟังก์ชั่นในโมดูล Enum ถูก จำกัด ไว้ที่ชื่อกล่าวคือการแจกแจงค่าในโครงสร้างข้อมูล ตัวอย่างโครงสร้างข้อมูลที่แจกแจงได้คือรายการทูเปิลแผนที่และอื่น ๆ โมดูล Enum มีฟังก์ชันมากกว่า 100 รายการเพื่อจัดการกับ enums เราจะพูดถึงหน้าที่สำคัญบางประการในบทนี้
ฟังก์ชันทั้งหมดเหล่านี้ใช้เวลานับเป็นองค์ประกอบแรกและฟังก์ชันที่สองและทำงานกับพวกเขา ฟังก์ชั่นอธิบายไว้ด้านล่าง
ทั้งหมด?
เมื่อเราใช้ allเหรอ? ฟังก์ชันคอลเลกชันทั้งหมดต้องประเมินเป็นจริงมิฉะนั้นเท็จจะถูกส่งกลับ ตัวอย่างเช่นเพื่อตรวจสอบว่าองค์ประกอบทั้งหมดในรายการเป็นจำนวนคี่หรือไม่
res = Enum.all?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end)
IO.puts(res)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
false
เนื่องจากองค์ประกอบทั้งหมดของรายการนี้ไม่ได้แปลก
ใด ๆ ?
ตามชื่อที่แนะนำฟังก์ชันนี้จะคืนค่าจริงหากองค์ประกอบใด ๆ ของคอลเล็กชันประเมินว่าเป็นจริง ตัวอย่างเช่น -
res = Enum.any?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end)
IO.puts(res)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
true
ก้อน
ฟังก์ชันนี้แบ่งคอลเลกชันของเราออกเป็นชิ้นเล็ก ๆ ตามขนาดที่ระบุไว้เป็นอาร์กิวเมนต์ที่สอง ตัวอย่างเช่น -
res = Enum.chunk([1, 2, 3, 4, 5, 6], 2)
IO.puts(res)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
[[1, 2], [3, 4], [5, 6]]
แต่ละ
อาจจำเป็นต้องทำซ้ำในคอลเลคชันโดยไม่ต้องสร้างค่าใหม่สำหรับกรณีนี้เราใช้ไฟล์ each ฟังก์ชัน -
Enum.each(["Hello", "Every", "one"], fn(s) -> IO.puts(s) end)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
Hello
Every
one
แผนที่
ในการใช้ฟังก์ชันของเรากับแต่ละรายการและสร้างคอลเล็กชันใหม่เราใช้ฟังก์ชันแผนที่ เป็นโครงสร้างที่มีประโยชน์ที่สุดอย่างหนึ่งในการเขียนโปรแกรมเชิงฟังก์ชันเนื่องจากค่อนข้างแสดงออกและสั้น ให้เราพิจารณาตัวอย่างเพื่อทำความเข้าใจสิ่งนี้ เราจะเพิ่มค่าที่เก็บไว้ในรายการเป็นสองเท่าและเก็บไว้ในรายการใหม่res -
res = Enum.map([2, 5, 3, 6], fn(a) -> a*2 end)
IO.puts(res)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
[4, 10, 6, 12]
ลด
reduceฟังก์ชันช่วยให้เราลดการนับเป็นค่าเดียว ในการทำเช่นนี้เราจัดหาตัวสะสมเสริม (5 ในตัวอย่างนี้) เพื่อส่งผ่านไปยังฟังก์ชันของเรา หากไม่มีการระบุตัวสะสมจะใช้ค่าแรก -
res = Enum.reduce([1, 2, 3, 4], 5, fn(x, accum) -> x + accum end)
IO.puts(res)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
15
ตัวสะสมคือค่าเริ่มต้นที่ส่งไปยัง fn. ตั้งแต่การโทรครั้งที่สองเป็นต้นไปค่าที่ส่งคืนจากการโทรครั้งก่อนจะถูกส่งต่อแบบสะสม นอกจากนี้เรายังสามารถใช้การลดโดยไม่ต้องใช้ตัวสะสม -
res = Enum.reduce([1, 2, 3, 4], fn(x, accum) -> x + accum end)
IO.puts(res)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
10
uniq
ฟังก์ชัน uniq จะลบรายการที่ซ้ำกันออกจากคอลเล็กชันของเราและส่งคืนเฉพาะชุดขององค์ประกอบในคอลเล็กชัน ตัวอย่างเช่น -
res = Enum.uniq([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
IO.puts(res)
เมื่อรันโปรแกรมด้านบนจะให้ผลลัพธ์ดังนี้ -
[1, 2, 3, 4]
การประเมินอย่างกระตือรือร้น
ฟังก์ชั่นทั้งหมดในโมดูล Enum มีความกระตือรือร้น ฟังก์ชั่นจำนวนมากคาดหวังว่าจะสามารถแจงนับและส่งคืนรายการกลับ ซึ่งหมายความว่าเมื่อดำเนินการหลายอย่างกับ Enum แต่ละการดำเนินการจะสร้างรายการกลางจนกว่าเราจะไปถึงผลลัพธ์ ให้เราพิจารณาตัวอย่างต่อไปนี้เพื่อทำความเข้าใจสิ่งนี้ -
odd? = &(odd? = &(rem(&1, 2) != 0)
res = 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum
IO.puts(res)
เมื่อรันโปรแกรมข้างต้นจะให้ผลลัพธ์ดังนี้ -
7500000000
ตัวอย่างข้างต้นมีท่อของการดำเนินงาน เราเริ่มต้นด้วยช่วงจากนั้นคูณแต่ละองค์ประกอบในช่วงด้วย 3 การดำเนินการแรกนี้จะสร้างและส่งคืนรายการที่มีรายการ 100_000 รายการ จากนั้นเราเก็บองค์ประกอบแปลก ๆ ทั้งหมดจากรายการสร้างรายการใหม่ตอนนี้มี 50_000 รายการจากนั้นเราจะรวมรายการทั้งหมด
|> สัญลักษณ์ที่ใช้ในตัวอย่างข้อมูลด้านบนคือ pipe operator: เพียงแค่รับเอาต์พุตจากนิพจน์ทางด้านซ้ายและส่งผ่านเป็นอาร์กิวเมนต์แรกไปยังการเรียกใช้ฟังก์ชันทางด้านขวา คล้ายกับ Unix | ตัวดำเนินการ จุดประสงค์คือเพื่อเน้นการไหลของข้อมูลที่ถูกเปลี่ยนโดยชุดฟังก์ชัน
ปราศจาก pipe ตัวดำเนินการรหัสดูซับซ้อน -
Enum.sum(Enum.filter(Enum.map(1..100_000, &(&1 * 3)), odd?))
อย่างไรก็ตามเรามีฟังก์ชั่นอื่น ๆ อีกมากมาย แต่มีคำอธิบายที่สำคัญเพียงไม่กี่อย่างเท่านั้น