web-dev-qa-db-fra.com

Rechercher la première condition de correspondance des éléments dans Swift (par exemple EKSource)

Je voudrais trouver le premier EKSource de type EKSourceType.Local avec une expression de ligne "unique" dans Swift. Voici ce que j'ai actuellement:

let eventSourceForLocal = 
    eventStore.sources[eventStore.sources.map({ $0.sourceType })
        .indexOf(EKSourceType.Local)!]

Existe-t-il une meilleure façon de procéder (comme sans mappage et/ou avec une version générique de find)?

33
Drux

Il existe une version de indexOf qui prend une fermeture de prédicat - utilisez-la pour trouver l'index de la première source locale (si elle existe), puis utilisez cet index sur eventStore.sources:

if let index = eventStore.sources.indexOf({ $0.sourceType == .Local }) {
    let eventSourceForLocal = eventStore.sources[index]
}

Alternativement, vous pouvez ajouter une méthode générique find via une extension sur SequenceType:

extension SequenceType {
    func find(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
        for element in self {
            if try predicate(element) {
                return element
            }
        }
        return nil
    }
}

let eventSourceForLocal = eventStore.sources.find({ $0.sourceType == .Local })

(Pourquoi n'est-ce pas déjà là?)

38
Nate Cook

Alternativement dans Swift3, vous pouvez utiliser:

let local = eventStore.sources.first(where: {$0.sourceType == .Local}) 
81
Bueno

Je ne comprends pas du tout pourquoi vous utilisez map. Pourquoi ne pas utiliser filter? Vous vous retrouverez alors avec toutes les sources locales, mais en réalité il n'y en aura probablement qu'une, ou aucune, et vous pouvez facilement le découvrir en demandant la première (ce sera nil s'il n'y en a pas 'Ton):

let local = eventStore.sources.filter{$0.sourceType == .Local}.first
19
matt

Swift 4 solution qui gère également la situation lorsqu'il n'y a pas d'éléments dans votre tableau qui correspondent à votre condition:

if let firstMatch = yourArray.first{$0.id == lookupId} {
  print("found it: \(firstMatch)")
} else {
  print("nothing found :(")
}
11
budidino

Essayons quelque chose de plus fonctionnel:

let arr = [0,1,2,3]
let result = arr.lazy.map{print("????");return $0}.first(where: {$0 == 2})
print(result)//3x ???? then 2

Qu'est-ce qui est cool à ce sujet?
Vous avez accès à l'élément ou i pendant votre recherche. Et c'est fonctionnel.

2
eonist

Pour Swift 3, vous devrez apporter quelques petites modifications à la réponse de Nate ci-dessus. Voici la version Swift 3:

public extension Sequence {
    func find(predicate: (Iterator.Element) throws -> Bool) rethrows -> Iterator.Element? {
        for element in self {
            if try predicate(element) {
                return element
            }
        }
        return nil
    }
}

Modifications: SequenceType> Sequence, Self.Generator.Element> Iterator.Element

1
Tyler Sheaffer