0Pricing
Swift Academy · บทเรียน

การใช้ KeyPaths ในคอลเลกชัน

เรียงลำดับและแปลงคอลเลกชันตามเส้นทางคีย์

การใช้ KeyPaths ในคอลเลกชัน เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คีย์พาธโดดเด่นในคอลเลกชัน

การดำเนินการกับคอลเลกชัน เช่น map, sorted และ filter มักทำเพียง read คุณสมบัติหนึ่งรายการของแต่ละองค์ประกอบ คีย์พาธช่วยให้คุณสื่อเจตนานั้นได้โดยไม่ต้องเขียนคลอเชอร์

Swift ยอมรับคีย์พาธได้ทุกตำแหน่งที่คาดว่าจะเป็นฟังก์ชันซึ่งรับอาร์กิวเมนต์เดียวและคืนค่า เนื่องจากคีย์พาธสามารถใช้เป็นฟังก์ชันจาก Root ไปยัง Value ได้

struct Person {
    let name: String
    let age: Int
}

let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let names = people.map(\.name)
print(names)

map แบบย่อด้วยคีย์พาธ

การส่ง map(\.property) เทียบเท่ากับการเขียนคลอเชอร์ที่คืนค่าคุณสมบัตินั้น แต่สั้นและชัดเจนกว่า เครื่องหมายแบ็กสแลชนำหน้าและจุดช่วยให้คอมไพเลอร์อนุมานชนิดขององค์ประกอบได้

ลองเปรียบเทียบสองรูปแบบด้านล่าง ทั้งสองรูปแบบให้ผลลัพธ์เดียวกัน

struct Person {
    let name: String
    let age: Int
}

let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let closureForm = people.map { $0.age }
let keyPathForm = people.map(\.age)
print(closureForm)
print(keyPathForm)

sorted(by:) พร้อมการเปรียบเทียบด้วยคีย์พาธ

หากต้องการเรียงลำดับตามคุณสมบัติ คุณยังคงต้องเขียนคลอเชอร์เปรียบเทียบขนาดเล็ก แต่สามารถอ่านคุณสมบัติผ่านคีย์พาธภายในคลอเชอร์เพื่อให้โค้ดชัดเจนขึ้น

ที่นี่เราเรียงผู้คนจากอายุน้อยไปมากโดยเปรียบเทียบค่า age ของแต่ละคน

struct Person {
    let name: String
    let age: Int
}

let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let path = \Person.age
let sorted = people.sorted { $0[keyPath: path] < $1[keyPath: path] }
print(sorted.map(\.name))

ตัวช่วยเรียงลำดับที่นำกลับมาใช้ใหม่ได้

คุณสามารถเขียนตัวช่วยทั่วไปที่เรียงอาร์เรย์ใดก็ได้ตามคุณสมบัติที่เปรียบเทียบได้ โดยรับคุณสมบัตินั้นเป็นอาร์กิวเมนต์คีย์พาธ วิธีนี้ทำให้การเรียงลำดับตามช่องข้อมูลกลายเป็นคำสั่งบรรทัดเดียวที่ใช้ซ้ำได้ทั่วทั้งโค้ดของคุณ

ข้อจำกัด T: Comparable รับรองว่าคุณสมบัตินั้นสามารถนำมาเรียงลำดับได้

func sorted<E, T: Comparable>(_ array: [E], by path: KeyPath<E, T>) -> [E] {
    array.sorted { $0[keyPath: path] < $1[keyPath: path] }
}

struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
print(sorted(people, by: \.age).map(\.name))

การกรองผ่านคีย์พาธ

สำหรับ filter คุณต้องใช้เงื่อนไขตรวจสอบที่คืนค่าเป็น Bool ดังนั้นคีย์พาธของคุณสมบัติแบบเดี่ยวจะใช้ได้โดยตรงก็ต่อเมื่อคุณสมบัตินั้นเป็น Bool อยู่แล้ว

ที่นี่แต่ละงานมีแฟล็ก isDone และเรากรองข้อมูลโดยใช้รูปแบบคีย์พาธแบบย่อ

struct Task {
    let title: String
    let isDone: Bool
}

let tasks = [Task(title: "A", isDone: true), Task(title: "B", isDone: false)]
let finished = tasks.filter(\.isDone)
print(finished.map(\.title))

การกรองตามคุณสมบัติที่ไม่ใช่บูลีน

เมื่อกรองตามคุณสมบัติที่ไม่ใช่บูลีน ให้ read คุณสมบัตินั้นผ่านคีย์พาธภายในคลอเชอร์แล้วนำมาเปรียบเทียบ ตัวช่วยทั่วไปสามารถเก็บรูปแบบนี้ไว้ใช้กับคุณสมบัติใดก็ได้ที่เปรียบเทียบความเท่ากันได้

ที่นี่เราเก็บไว้เฉพาะ people ที่มี city ตรงกับค่าเป้าหมาย

struct Person { let name: String; let city: String }

func filter<E, T: Equatable>(_ array: [E], _ path: KeyPath<E, T>, equals value: T) -> [E] {
    array.filter { $0[keyPath: path] == value }
}

let people = [Person(name: "Ana", city: "Oslo"), Person(name: "Ben", city: "Rome")]
print(filter(people, \.city, equals: "Oslo").map(\.name))

max และ min ตามคีย์พาธ

เมธอด max(by:) และ min(by:) รับคลอเชอร์เปรียบเทียบเช่นเดียวกับ sorted ให้ read คุณสมบัติผ่านคีย์พาธเพื่อค้นหาองค์ประกอบที่มีค่ามากที่สุดหรือน้อยที่สุด

ที่นี่เราค้นหาบุคคลที่เป็น oldest

struct Person { let name: String; let age: Int }

let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25), Person(name: "Cy", age: 41)]
let path = \Person.age
if let oldest = people.max(by: { $0[keyPath: path] < $1[keyPath: path] }) {
    print(oldest.name)
}

การรวมค่าคุณสมบัติด้วย reduce

คุณสามารถใช้ map(\.property) ร่วมกับ reduce เพื่อรวมค่าช่องข้อมูลตัวเลข เริ่มจากดึงค่าของแต่ละองค์ประกอบให้เหลือเป็นตัวเลขที่ต้องการ แล้วจึงนำมาบวกกัน

ที่นี่เรารวมอายุทั้งหมดในกระบวนการต่อเนื่องเดียว

struct Person { let name: String; let age: Int }

let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let totalAge = people.map(\.age).reduce(0, +)
print(totalAge)

การจัดกลุ่มตามคีย์พาธ

Dictionary(grouping:by:) จัดองค์ประกอบลงกลุ่มตามผลลัพธ์ของคลอเชอร์ ให้ read คุณสมบัติผ่านคีย์พาธเพื่อจัดกลุ่มตามช่องข้อมูลนั้น

ที่นี่ people จะถูกจัดกลุ่มตาม city ลงในพจนานุกรมที่มีค่าเป็นอาร์เรย์

struct Person { let name: String; let city: String }

let people = [
    Person(name: "Ana", city: "Oslo"),
    Person(name: "Ben", city: "Rome"),
    Person(name: "Cy", city: "Oslo")
]
let path = \Person.city
let byCity = Dictionary(grouping: people, by: { $0[keyPath: path] })
print(byCity["Oslo"]?.map(\.name) ?? [])

การเรียงลำดับหลายช่องข้อมูล

หากต้องการเรียงตามช่องข้อมูลหนึ่งและใช้ช่องข้อมูลอื่นตัดสินเมื่อค่าเท่ากัน ให้เปรียบเทียบคีย์พาธหลักก่อน แล้วใช้คีย์พาธรองเป็น fallback เมื่อค่าหลักเท่ากัน

ที่นี่เราเรียงตาม age แล้วเรียงตามชื่อเมื่อ age เท่ากัน

struct Person { let name: String; let age: Int }

let people = [
    Person(name: "Zoe", age: 30),
    Person(name: "Ana", age: 30),
    Person(name: "Ben", age: 25)
]
let sorted = people.sorted {
    if $0[keyPath: \Person.age] != $1[keyPath: \Person.age] {
        return $0.age < $1.age
    }
    return $0.name < $1.name
}
print(sorted.map(\.name))

เหตุใดคีย์พาธจึงดีกว่าคลอเชอร์ในกรณีนี้

การใช้คีย์พาธในคำสั่งของคอลเลกชันช่วยลดโค้ดประกอบที่ซ้ำซ้อน ลดโอกาสพิมพ์ผิดในตัวคลอเชอร์ และทำให้เจตนาชัดเจนว่าคุณกำลังดึงข้อมูลจากช่องข้อมูลเพียงรายการเดียว

สำหรับการแปลงข้อมูลที่ซับซ้อน คลอเชอร์ยังคงเป็นเครื่องมือที่เหมาะสม แต่สำหรับการ read คุณสมบัติโดยตรง \.property เป็นตัวเลือกที่ชัดเจนที่สุด

struct Product { let name: String; let price: Double }

let products = [Product(name: "Pen", price: 2), Product(name: "Pad", price: 5)]
let names = products.map(\.name)
let prices = products.map(\.price)
print(names)
print(prices)

ตรวจสอบด่วน: คีย์พาธใน map

เลือกรูปแบบคีย์พาธแบบกระชับสำหรับดึงคุณสมบัติหนึ่งรายการจากแต่ละองค์ประกอบ

ทบทวน: คีย์พาธในคอลเลกชัน

คุณได้เห็นแล้วว่าคีย์พาธช่วยทำให้โค้ดคอลเลกชันกระชับขึ้นได้อย่างไร:

  • map(\.property) ดึงค่าจากช่องข้อมูลหนึ่งรายการโดยไม่ต้องใช้คลอเชอร์
  • filter(\.boolProperty) ใช้ได้โดยตรงกับช่องข้อมูลแบบ Bool ส่วนช่องข้อมูลชนิดอื่นให้ใช้คลอเชอร์ร่วมกับ [keyPath:]
  • การเรียงลำดับ max และ min จะ read คุณสมบัติผ่านคีย์พาธภายในคลอเชอร์เปรียบเทียบ
  • ตัวช่วยทั่วไปที่รับ KeyPath ช่วยเปลี่ยนการเรียงลำดับและการกรองตามช่องข้อมูลให้เป็นคำสั่งบรรทัดเดียวที่นำกลับมาใช้ใหม่ได้

ถัดไปคุณจะเรียนรู้คีย์พาธแบบเขียนได้ ซึ่งช่วยให้คุณกำหนดค่าได้ ไม่ใช่แค่อ่านค่า

struct Person { let name: String; let age: Int }

let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let youngestFirst = people.sorted { $0[keyPath: \Person.age] < $1[keyPath: \Person.age] }
print(youngestFirst.map(\.name))

คำถามที่พบบ่อย

บทเรียน “การใช้ KeyPaths ในคอลเลกชัน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การใช้ KeyPaths ในคอลเลกชัน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การใช้ KeyPaths ในคอลเลกชัน”

เรียงลำดับและแปลงคอลเลกชันตามเส้นทางคีย์ คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การใช้ KeyPaths ในคอลเลกชัน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม

ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน KeyPath
  2. การใช้ KeyPaths ในคอลเลกชัน
  3. KeyPath ที่เขียนได้และอ้างอิงได้
  4. @dynamicMemberLookup
← กลับไปที่ Swift Academy