Published on

Swiftda KeyPath

Authors

KeyPath β€” Swift da property ga "yo'l" ko'rsatuvchi maxsus tur. Oddiy closure { $0.ism } yozish o'rniga \.ism deyish mumkin. Bu kodni qisqartiradi va ifodali qiladi. KeyPath funksiya sifatida ham ishlatilishi mumkin (Swift 5.2+) β€” map(\.ism) kabi.

KeyPath turlari: KeyPath<Root, Value> β€” faqat o'qish, WritableKeyPath<Root, Value> β€” o'qish va yozish (var property lar uchun), ReferenceWritableKeyPath β€” class ning var property siga yozish.

KeyPath asoslari

KeyPath yaratish uchun \Tur.property formatida yoziladi. Qiymat olish uchun ob'ekt[keyPath: \.property] ishlatiladi. let property ga yozib bo'lmaydi, faqat var property ga WritableKeyPath orqali yozish mumkin.

struct Talaba {
    let ism: String
    var baho: Int
    let guruh: String
}

// ═══════════════════════════════════════
//  KEYPATH YARATISH
// ═══════════════════════════════════════
// \Talaba.ism β€” Talaba turidagi ism property siga yo'l
let ismKeyPath: KeyPath<Talaba, String> = \Talaba.ism
let bahoKeyPath: WritableKeyPath<Talaba, Int> = \Talaba.baho

let ali = Talaba(ism: "Ali", baho: 5, guruh: "A")

// KeyPath bilan qiymat olish
let ism = ali[keyPath: ismKeyPath]    // "Ali"
let ism2 = ali[keyPath: \.ism]       // "Ali" β€” qisqa yozuv


// ═══════════════════════════════════════
//  WRITABLEKEYPATH β€” yozish mumkin
// ═══════════════════════════════════════
var vali = Talaba(ism: "Vali", baho: 3, guruh: "B")
vali[keyPath: \.baho] = 5  // var property ga yozish βœ…
// vali[keyPath: \.ism] = "X"  // ❌ let β€” yozib bo'lmaydi

KeyPath va Higher-Order Functions

KeyPath ning eng kuchli tomoni β€” map, sorted, max kabi funksiyalar bilan birgalikda ishlatilishi. talabalar.map(\.ism) β€” talabalar.map { $0.ism } bilan bir xil, lekin ancha qisqa va o'qish oson.

let talabalar = [
    Talaba(ism: "Ali", baho: 5, guruh: "A"),
    Talaba(ism: "Vali", baho: 3, guruh: "B"),
    Talaba(ism: "Gani", baho: 4, guruh: "A"),
    Talaba(ism: "Doni", baho: 5, guruh: "B"),
]

// ═══════════════════════════════════════
//  MAP BILAN KEYPATH
// ═══════════════════════════════════════
// Eski usul:
let ismlar1 = talabalar.map { $0.ism }

// KeyPath bilan β€” qisqa va ifodali:
let ismlar2 = talabalar.map(\.ism)
// ["Ali", "Vali", "Gani", "Doni"]

let baholar = talabalar.map(\.baho)
// [5, 3, 4, 5]


// ═══════════════════════════════════════
//  FILTER BILAN KEYPATH
// ═══════════════════════════════════════
// KeyPath ni predicate sifatida (extension kerak):
let yuqoriBaholar = talabalar.filter { $0.baho >= 4 }

// sorted bilan
let tartiblangan = talabalar.sorted { $0.baho < $1.baho }


// ═══════════════════════════════════════
//  MIN/MAX BILAN KEYPATH
// ═══════════════════════════════════════
let engYuqori = talabalar.max { $0.baho < $1.baho }
print(engYuqori?.ism ?? "")  // "Ali" yoki "Doni"

KeyPath bilan amaliy misollar

KeyPath ning chinakam kuchi generik funksiyalar bilan namoyon bo'ladi. Masalan, istalgan property bo'yicha guruhlash funksiyasi yozish mumkin β€” bir safar yozib, har xil property lar bilan ishlatish. extension bilan massivga yangi metodlar qo'shish ham mumkin.

// ═══════════════════════════════════════
//  GENERIK FUNKSIYA β€” KeyPath bilan
// ═══════════════════════════════════════

// Istalgan property bo'yicha guruhlash
func guruhla<T, K: Hashable>(
    _ massiv: [T],
    boyicha keyPath: KeyPath<T, K>
) -> [K: [T]] {
    Dictionary(grouping: massiv) { $0[keyPath: keyPath] }
}

let guruhlar = guruhla(talabalar, boyicha: \.guruh)
// ["A": [Ali, Gani], "B": [Vali, Doni]]

let bahoBoyicha = guruhla(talabalar, boyicha: \.baho)
// [5: [Ali, Doni], 3: [Vali], 4: [Gani]]


// ═══════════════════════════════════════
//  YIGINDI β€” KeyPath bilan
// ═══════════════════════════════════════
extension Sequence {
    func yigindi<T: Numeric>(of keyPath: KeyPath<Element, T>) -> T {
        reduce(.zero) { $0 + $1[keyPath: keyPath] }
    }
}

let umumiyBaho = talabalar.yigindi(of: \.baho)  // 17

🎯 Topshiriq

Mahsulot struct yarating (nomi, narxi, kategoriya). map(\.nomi) bilan nomlar ro'yxatini oling. guruhla(_:boyicha:) funksiyasini ishlatib kategoriya bo'yicha guruhlang. yigindi(of:) extension bilan umumiy narxni hisoblang.

Buy mea coffee