オブジェクト配列からプロパティ値の配列を取得する


113

というクラスがあり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、その配列内のすべてのオブジェクトのsを新しい配列に抽出することです。

私もこの同様の質問を見つけました。しかし、それはObjective-Cにあるため、valueForKeyPathこれを達成するために使用しています。

Swiftでこれを行うにはどうすればよいですか?

回答:


234

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 }

1
それがのmap機能です。これは、の配列をフィールドで満たされEmployeeたの配列に変換Intidます。これは、「すべてのインスタンスからidフィールドを抽出Employeeして配列に入れる」と言うことと同じです
Antonio

4
@いする、この答えはあなたが望むことを正確に行います。s の配列からidsすべてのid値のと呼ばれる新しい配列を作成しますEmployee。元の配列はそのままになっていることに注意してください。
vacawama 2015

2
Swift 2ベータ版では、正しい構文は次のようになりますarray.map( { $0.id })
TotoroTotoro

10
オプションを使用している場合は、確認してください!それ。何時間もかかった。
Chris

2
@Chrisの強制アンラップは、通常は不適切です。nilの場合、アプリがクラッシュします。厳密に必要な場合にのみ使用し、代わりにオプションのバインディング(またはその他の「ソフト」アンラッピング)を使用してください
Antonio

81

Swift 5は、類似したオブジェクトの配列からプロパティ値の配列を取得する多くの方法を提供します。必要に応じて、6つの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ループはのイテレータwhileに対するループにすぎませんsequence(詳細については、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. とプロトコルにstruct準拠したの使用IteratorProtocolSequence

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

5
巨大な...それは私が理解できる限り完全な可能なアプローチのリスト
Injectios
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.