Swift

【Swift】Arrayに検索機能を追加する

More than 1 year has passed since last update.

SwiftArray にオブジェクトのインデックス番号or nil を返す検索用のメソッドを追加してみました。

ArrayExtension.swift
import Foundation

extension Array {

    func find(includeElement: T -> Bool) -> Int? {
        for (index, element) in enumerate(self) {
            if includeElement(element) {
                return index
            }
        }
        return nil
    }
}

引数のincludeElementClosuerなので、Arrayの中に入っているクラスを受け取って、Boolを返せばなんでも大丈夫です。

以下、サンプルです。

Playground.swift
class Person {
    var firstName: String
    var lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}

var hoge = Person(firstName: "hoge", lastName: "hoge")
var fuga = Person(firstName: "fuga", lastName: "fuga")
var hogeFuga = Person(firstName: "hoge", lastName: "fuga")

var persons:[Person] = [hoge, fuga, hogeFuga]

if let hogeIndex = persons.find({ $0 == hoge }) {
    println(hogeIndex)
}

2015/4/20 追記

@satoshiaさん、@koherさんより配列の要素が重複した場合のことを考えた処理をお教えいただいたので、記載させていただきます!
御二方、改めてありがとうございました!

@satoshiaさんより...

要素が重複している場合を考えて、 要素のindex番号とその要素を配列にして返すメソッド をお教えいただきました!

extension Array {
    func findAll(includeElement: T -> Bool) -> [(Int, T)] {
        let seq = zip(0..<self.count, self)
        return Swift.filter(seq) { includeElement($0.1) }
    }
}

@koherさんより

こちらはもっとシンプルに書かれています!

extension Array {
    func find(includeElement: T -> Bool) -> Int? {
        return Swift.filter(enumerate(self)) { includeElement($0.1) }.first.map { $0.0 }
    }
}

以上です。