Dapatkan larik nilai properti dari larik objek

113

Ada kelas yang disebut Employee.

class Employee {

    var id: Int
    var firstName: String
    var lastName: String
    var dateOfBirth: NSDate?

    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }
}

Dan saya memiliki berbagai Employeeobjek. Apa yang saya butuhkan sekarang adalah mengekstrak ids dari semua objek dalam array itu ke dalam array baru.

Saya juga menemukan pertanyaan serupa ini . Tapi itu di Objective-C jadi itu digunakan valueForKeyPathuntuk mencapai ini.

Bagaimana saya bisa melakukan ini di Swift?

Isuru
sumber

Jawaban:

234

Anda dapat menggunakan mapmetode, yang mengubah sebuah array dari tipe tertentu menjadi sebuah array dari tipe lain - dalam kasus Anda, dari array Employeemenjadi array dari Int:

var array = [Employee]()
array.append(Employee(id: 4, firstName: "", lastName: ""))
array.append(Employee(id: 2, firstName: "", lastName: ""))

let ids = array.map { $0.id }
Antonio
sumber
1
Itulah yang mapdilakukannya - itu mengubah array Employeemenjadi array Int, diisi dengan idbidang. Yang setara dengan mengatakan "ekstrak bidang id dari semua contoh Employeedan letakkan ke dalam array"
Antonio
4
@Isuru, jawaban ini melakukan apa yang Anda inginkan. Ini membuat array baru yang disebut idssemua idnilai dari array Employees. Catatan, ini membiarkan array asli tetap utuh.
vacawama
2
Sepertinya di Swift 2 beta sintaks yang benar adalaharray.map( { $0.id })
TotoroTotoro
10
jika Anda menggunakan opsional, pastikan Anda! Itu. Aku butuh waktu berjam-jam.
Chris
2
@Chris terpaksa membuka bungkus biasanya praktik yang buruk, karena jika nihil akan menyebabkan aplikasi macet. Gunakan hanya jika benar-benar diperlukan, dan lebih suka penjilidan opsional (atau pembungkusan "lunak" lainnya) sebagai gantinya
Antonio
81

Swift 5 menawarkan banyak cara untuk mendapatkan larik nilai properti dari larik objek serupa. Sesuai dengan kebutuhan Anda, Anda dapat memilih salah satu dari enam contoh kode Playground berikut untuk menyelesaikan masalah Anda.


1. Menggunakan mapmetode

Dengan Swift, tipe yang sesuai dengan Sequenceprotokol memiliki map(_:)metode. Kode contoh berikut menunjukkan cara menggunakannya:

class Employee {
    
    let id: Int, firstName: String, lastName: String
    
    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }

}

let employeeArray = [
    Employee(id: 1, firstName: "Jon", lastName: "Skeet"),
    Employee(id: 2, firstName: "Darin", lastName: "Dimitrov"),
    Employee(id: 4, firstName: "Hans", lastName: "Passant")
]

let idArray = employeeArray.map({ (employee: Employee) -> Int in
    employee.id
})
// let idArray = employeeArray.map { $0.id } // also works
print(idArray) // prints [1, 2, 4]

2. Menggunakan forloop

class Employee {
    
    let id: Int, firstName: String, lastName: String

    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }

}

let employeeArray = [
    Employee(id: 1, firstName: "Jon", lastName: "Skeet"),
    Employee(id: 2, firstName: "Darin", lastName: "Dimitrov"),
    Employee(id: 4, firstName: "Hans", lastName: "Passant")
]

var idArray = [Int]()    
for employee in employeeArray {
    idArray.append(employee.id)
}
print(idArray) // prints [1, 2, 4]

3. Menggunakan whileloop

Perhatikan bahwa dengan Swift, di belakang layar, sebuah forloop hanyalah sebuah whileloop di atas sequenceiterator (lihat IteratorProtocol untuk lebih jelasnya).

class Employee {
    
    let id: Int, firstName: String, lastName: String
    
    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }

}

let employeeArray = [
    Employee(id: 1, firstName: "Jon", lastName: "Skeet"),
    Employee(id: 2, firstName: "Darin", lastName: "Dimitrov"),
    Employee(id: 4, firstName: "Hans", lastName: "Passant")
]

var idArray = [Int]()
var iterator = employeeArray.makeIterator()    
while let employee = iterator.next() {
    idArray.append(employee.id)
}
print(idArray) // prints [1, 2, 4]

4. Menggunakan structyang sesuai dengan IteratorProtocoldan Sequenceprotokol

class Employee {
    
    let id: Int, firstName: String, lastName: String
    
    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }
    
}

struct EmployeeSequence: Sequence, IteratorProtocol {
    
    let employeeArray: [Employee]
    private var index = 0
    
    init(employeeArray: [Employee]) {
        self.employeeArray = employeeArray
    }
    
    mutating func next() -> Int? {
        guard index < employeeArray.count else { return nil }
        defer { index += 1 }
        return employeeArray[index].id
    }
    
}

let employeeArray = [
    Employee(id: 1, firstName: "Jon", lastName: "Skeet"),
    Employee(id: 2, firstName: "Darin", lastName: "Dimitrov"),
    Employee(id: 4, firstName: "Hans", lastName: "Passant")
]
let employeeSequence = EmployeeSequence(employeeArray: employeeArray)
let idArray = Array(employeeSequence)
print(idArray) // prints [1, 2, 4]

5. Menggunakan Collectionekstensi protokol danAnyIterator

class Employee {
    
    let id: Int, firstName: String, lastName: String
    
    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }

}

extension Collection where Iterator.Element: Employee {
    
    func getIDs() -> Array<Int> {
        var index = startIndex
        let iterator: AnyIterator<Int> = AnyIterator {
            defer { index = self.index(index, offsetBy: 1) }
            return index != self.endIndex ? self[index].id : nil
        }
        return Array(iterator)
    }
    
}

let employeeArray = [
    Employee(id: 1, firstName: "Jon", lastName: "Skeet"),
    Employee(id: 2, firstName: "Darin", lastName: "Dimitrov"),
    Employee(id: 4, firstName: "Hans", lastName: "Passant")
]

let idArray = employeeArray.getIDs()
print(idArray) // prints [1, 2, 4]

6. Menggunakan KVC dan NSArray's value(forKeyPath:)metode

Perhatikan bahwa contoh ini perlu class Employeemewarisi dari NSObject.

import Foundation

class Employee: NSObject {

    @objc let id: Int, firstName: String, lastName: String

    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }

}

let employeeArray = [
    Employee(id: 1, firstName: "Jon", lastName: "Skeet"),
    Employee(id: 2, firstName: "Darin", lastName: "Dimitrov"),
    Employee(id: 4, firstName: "Hans", lastName: "Passant")
]

let employeeNSArray = employeeArray as NSArray
if let idArray = employeeNSArray.value(forKeyPath: #keyPath(Employee.id)) as? [Int] {
    print(idArray) // prints [1, 2, 4]
}
Imanou Petit
sumber
5
besar ... Sejauh yang saya mengerti, daftar pendekatan yang mungkin lengkap
Injectios