【问题标题】: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 中做到这一点?

【问题讨论】:

    标签: ios arrays 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(特别是注释掉的行),但很好的详尽列表!
    猜你喜欢
    • 2015-04-05
    • 1970-01-01
    • 2022-10-19
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 2015-06-10
    • 2023-01-27
    相关资源
    最近更新 更多