Nhận một mảng các giá trị thuộc tính từ một mảng đối tượng


113

Có một lớp được gọi là 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
    }
}

Và tôi có một mảng các Employeeđối tượng. Những gì tôi cần bây giờ là trích xuất ids của tất cả các đối tượng trong mảng đó thành một mảng mới.

Tôi cũng tìm thấy câu hỏi tương tự này . Nhưng nó nằm trong Objective-C nên nó đang sử dụng valueForKeyPathđể thực hiện điều này.

Làm thế nào tôi có thể làm điều này trong Swift?

Câu trả lời:


234

Bạn có thể sử dụng mapphương thức này để biến đổi một mảng của một kiểu nhất định thành một mảng thuộc kiểu khác - trong trường hợp của bạn là từ mảng này Employeesang mảng khác Int:

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

let ids = array.map { $0.id }

1
Đó là những gì maphiện - nó biến đổi một mảng Employeethành một mảng Intchứa đầy idtrường. Điều này tương đương với việc nói "trích xuất trường id từ tất cả các trường hợp của Employeevà đặt chúng vào một mảng"
Antonio

4
@Isuru, câu trả lời này thực hiện chính xác những gì bạn muốn. Nó tạo ra một mảng mới được gọi là idstất cả các idgiá trị từ mảng Employees. Lưu ý, nó để nguyên mảng ban đầu.
vacawama

2
Hình như trong Swift 2 beta cú pháp đúng sẽ làarray.map( { $0.id })
TotoroTotoro

10
nếu bạn đang sử dụng tùy chọn, hãy chắc chắn rằng bạn! nó. Đã khiến tôi mất nhiều giờ.
Chris

2
Việc mở gói cưỡng bức @Chris thường là một phương pháp không tốt, vì nếu không, nó sẽ khiến ứng dụng gặp sự cố. Sử dụng nó chỉ khi có yêu cầu nghiêm ngặt, và thích tùy chọn ràng buộc (hoặc bất kỳ khác "mềm" unwrapping) thay vì
Antonio

81

Swift 5 cung cấp nhiều cách để lấy một mảng giá trị thuộc tính từ một mảng các đối tượng tương tự. Theo nhu cầu của bạn, bạn có thể chọn một trong sáu ví dụ mã Playground sau để giải quyết vấn đề của mình.


1. mapPhương pháp sử dụng

Với Swift, các kiểu tuân theo Sequencegiao thức có một map(_:)phương thức. Mã mẫu sau đây cho thấy cách sử dụng nó:

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. Sử dụng forvòng lặp

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. Sử dụng whilevòng lặp

Lưu ý rằng với Swift, đằng sau hậu trường, một forvòng lặp chỉ là một whilevòng lặp qua sequencetrình lặp của một trình lặp (xem IteratorProtocol để biết thêm chi tiết).

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. Sử dụng một structphù hợp với IteratorProtocolvà các Sequencegiao thức

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. Sử dụng Collectionphần mở rộng giao thức vàAnyIterator

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. Sử dụng KVC và NSArray's value(forKeyPath:)phương pháp

Lưu ý rằng ví dụ này yêu cầu class Employeekế thừa từ 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]
}

5
khổng lồ ... Đó như xa như tôi hiểu hoàn chỉnh danh sách các phương pháp tốt
Injectios
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.