从对象数组中获取属性值数组

有一门课叫 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
}
}

我有一个 Employee对象的数组。我现在需要的是将该数组中所有对象的 id提取到一个新数组中。

我也发现了类似的 有个问题,但是它在 Objective-C 中,所以它使用 valueForKeyPath来完成。

在斯威夫特我怎么能这么做?

103428 次浏览

您可以使用 map方法,它将一个特定类型的数组转换为另一个类型的数组——在您的示例中,从 Employee的数组转换为 Int的数组:

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


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

Swift 5提供了许多方法来从类似对象的数组中获取属性值数组。根据您的需要,您可以选择一个 游乐场代码示例如下来解决您的问题。


1. 使用 map方法

使用 Swift,符合 Sequence协议的类型有一个 map(_:)方法。下面的示例代码演示如何使用它:

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. 使用 for循环

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. 使用 while循环

注意,对于 Swift,在幕后,for循环只是 sequence迭代器上的 while循环(更多细节见 迭代器协议)。

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. 使用符合 IteratorProtocolSequence协议的 struct

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. 使用 Collection协议扩展和 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. 使用 KVC 和 NSArrayvalue(forKeyPath:)方法

注意,这个示例要求从 NSObject继承 class Employee

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]
}