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

Posted

技术标签:

【中文标题】从对象数组中获取属性值数组【英文标题】:Get an array of property values from an object array 【发布时间】:2015-02-08 11:21:58 【问题描述】:

有一个类叫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 对象数组。我现在需要的是将该数组中所有这些对象的ids 提取到一个新数组中。

我也发现了类似的question。但它在 Objective-C 中,所以它使用 valueForKeyPath 来完成此操作。

如何在 Swift 中做到这一点?

【问题讨论】:

【参考方案1】:

您可以使用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 

【讨论】:

这就是map 所做的——它将Employee 的数组转换为Int 的数组,并用id 字段填充。这相当于说“从Employee的所有实例中提取id字段并将它们放入一个数组中” @Isuru,这个答案正是你想要的。它从Employees 数组中的所有id 值中创建一个名为ids 的新数组。请注意,它使原始数组保持不变。 看起来在 Swift 2 beta 中正确的语法应该是 array.map( $0.id ) 如果您使用的是可选的,请确保您!它。花了我几个小时。 @Chris 强制展开通常是一种不好的做法,因为如果为零,它将导致应用程序崩溃。仅在严格要求时使用它,并且更喜欢可选绑定(或任何其他“软”展开)【参考方案2】:

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


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 循环(有关详细信息,请参阅 IteratorProtocol)。

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:)方法

请注意,此示例要求 class Employee 继承自 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]

【讨论】:

巨大的......据我所知,这是完整的可能方法列表 可能已经停在#1(特别是注释掉的行),但很好的详尽列表!

以上是关于从对象数组中获取属性值数组的主要内容,如果未能解决你的问题,请参考以下文章

TS / JS-如果对象的属性与数组中的另一个属性相匹配,则从对象数组中获取“值”

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

通过属性值从对象数组中获取JavaScript对象[重复]

通过属性值从对象数组中获取JavaScript对象[重复]

javascript 从对象数组中获取不同的属性值

如何从对象数组中获取具有属性的列表,除非它包含具有特定值的另一个项目?