Найти первое условие соответствия элемента в массиве Swift (например, EKSource)
Я хотел бы найти первый EKSource
типа EKSourceType.Local
с "одиночным" строчным выражением в Swift. Вот что у меня сейчас есть:
let eventSourceForLocal =
eventStore.sources[eventStore.sources.map({ $0.sourceType })
.indexOf(EKSourceType.Local)!]
Есть ли лучший способ сделать это (например, без отображения и / или с общей версией find
)?
6 ответов
Там есть версия indexOf
это требует закрытия предиката - используйте его, чтобы найти индекс первого локального источника (если он существует), а затем используйте этот индекс на eventStore.sources
:
if let index = eventStore.sources.indexOf({ $0.sourceType == .Local }) {
let eventSourceForLocal = eventStore.sources[index]
}
В качестве альтернативы, вы можете добавить общий find
метод через расширение на 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 })
(Почему это уже не там?)
В качестве альтернативы в Swift3 вы можете использовать:
let local = eventStore.sources.first(where: {$0.sourceType == .Local})
Я не понимаю, почему вы используете map
совсем. Почему бы не использовать filter
? Затем вы получите все локальные источники, но на самом деле, вероятно, будет только один, или ни одного, и вы можете легко узнать, запросив первый (это будет nil
если его нет)
let local = eventStore.sources.filter{$0.sourceType == .Local}.first
РешениеSwift 4, которое также обрабатывает ситуацию, когда в вашем массиве нет элементов, соответствующих вашему условию:
if let firstMatch = yourArray.first{$0.id == lookupId} {
print("found it: \(firstMatch)")
} else {
print("nothing found :(")
}
Swift 5 Если вы хотите узнать из массива модели, укажите $0.keyTofound, иначе используйте $0
if let index = listArray.firstIndex(where: { $0.id == lookupId }) {
print("Found at \(index)")
} else {
print("Not found")
}
Давайте попробуем что-то более функциональное:
let arr = [0,1,2,3]
let result = arr.lazy.map{print("");return $0}.first(where: {$0 == 2})
print(result)//3x then 2
Что крутого в этом?
Вы получаете доступ к элементу или я во время поиска. И это функционально.
Для Swift 3 вам нужно внести несколько небольших изменений в ответ Нейта выше. Вот версия 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
}
}
Изменения: SequenceType
> Sequence
, Self.Generator.Element
> Iterator.Element