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

Isu*_*uru 97 arrays ios swift

有一个叫做的课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
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一系列的Employee对象.我现在需要的是id将该数组中所有这些对象的s 提取到一个新数组中.

我也发现了类似的问题.但它在Objective-C中,所以它valueForKeyPath用来实现这一目标.

我怎么能在Swift中做到这一点?

Ant*_*nio 210

您可以使用该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 }
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用可选项,请确保您!它.花了我几个小时. (8认同)
  • @Isuru,这个答案完全符合你的要求.它创建了一个名为`ids`的新数组,该数组来自`Employee`s数组中的所有`id`值.注意,它保持原始数组完整. (4认同)
  • 在Swift 2 beta中看起来正确的语法是`array.map({$ 0.id})` (2认同)
  • @Chris强制解包通常是一种不好的做法,因为如果为零则会导致应用程序崩溃.仅在严格要求时使用它,并且更喜欢可选的绑定(或任何其他"软"展开) (2认同)

Ima*_*tit 67

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


1.使用map方法

Swift为Sequence符合map(_:)协议(包括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")
]

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

2.使用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]()    
for employee in employeeArray {
    idArray.append(employee.id)
}
print(idArray) // prints [1, 2, 4]
Run Code Online (Sandbox Code Playgroud)

3.使用for循环

注意,对于Swift,在幕后,while循环只是迭代器上的sequence循环struct(有关更多详细信息,请参阅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]
Run Code Online (Sandbox Code Playgroud)

4.使用IteratorProtocol符合SequenceCollection协议的

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]
Run Code Online (Sandbox Code Playgroud)

5.使用AnyIterator协议扩展和NSArray

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]
Run Code Online (Sandbox Code Playgroud)

6.使用KVC和value(forKeyPath:)class Employee方法

请注意,此示例需要NSObject继承map.

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]
}
Run Code Online (Sandbox Code Playgroud)

有关更多示例,请参阅GitHub的迭代阵列存储库.

  • 巨大...据我所知,完整可能的方法列表 (4认同)