Найти объект с собственностью в массиве
Есть ли возможность получить объект из массива с определенным свойством? Или мне нужно зацикливать все объекты в моем массиве и проверить, является ли свойство конкретным, что я искал?
edit: Спасибо, что дали мне правильное направление, но у меня есть проблема, чтобы преобразовать это.
//снова отредактируйте: ОК, и если есть только один конкретный результат? Является ли это также возможным методом для этого?
let imageUUID = sender.imageUUID
let questionImageObjects = self.formImages[currentSelectedQuestion.qIndex] as [Images]!
// this is working
//var imageObject:Images!
/*
for (index, image) in enumerate(questionImageObjects) {
if(image.imageUUID == imageUUID) {
imageObject = image
}
}
*/
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
var imageObject = questionImageObjects.filter( { return $0.imageUUID == imageUUID } )
Ответы
Ответ 1
//это не работает - NSArray не является подтипом Images - так что, если есть только один возможный результат?
У вас нет способа доказать во время компиляции, что в массиве есть только один возможный результат. То, что вы действительно просите, - это первый результат сопоставления. Самый простой (хотя и не самый быстрый) - просто взять первый элемент результата фильтра:
let imageObject = questionImageObjects.filter{ $0.imageUUID == imageUUID }.first
imageObject
теперь будет необязательным, так как возможно, что ничего не соответствует.
Если поиск по всему массиву занимает много времени, вы можете легко создать функцию firstMatching
, которая вернет (дополнительный) первый элемент, соответствующий замыканию, но для коротких массивов это будет просто и просто.
Как отмечает charles, в Swift 3 это встроено:
questionImageObjects.first(where: { $0.imageUUID == imageUUID })
Ответ 2
Изменить 2016-05-05: Swift 3 будет включать first(where:)
.
В Swift 2 вы можете использовать indexOf
, чтобы найти индекс первого элемента массива, который соответствует предикату.
let index = questionImageObjects.indexOf({$0.imageUUID == imageUUID})
Это бит быстрее по сравнению с filter
, так как он будет остановлен после первого совпадения. (Альтернативно, вы можете использовать последовательность lazy
.)
Однако, это немного раздражает, что вы можете получить только индекс, а не сам объект. Для удобства я использую следующее расширение:
extension CollectionType {
func find(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
return try indexOf(predicate).map({self[$0]})
}
}
Затем выполняются следующие работы:
questionImageObjects.find({$0.imageUUID == imageUUID})
Ответ 3
Да, вы можете использовать метод filter
, который принимает замыкание, где вы можете установить логическое выражение.
Пример:
struct User {
var firstName: String?
var lastName: String?
}
let users = [User(firstName: "John", lastName: "Doe"), User(firstName: "Bill", lastName: "Clinton"), User(firstName: "John", lastName: "Travolta")];
let johns = users.filter( { return $0.firstName == "John" } )
Обратите внимание, что filter
возвращает массив, содержащий все элементы, удовлетворяющие логическому выражению.
Дополнительная информация в Справочник по библиотеке
Ответ 4
Вот другой способ получить конкретный объект, используя свойство объекта для поиска объекта в массиве.
if arrayTicketsListing.contains({ $0.status_id == "2" }) {
let ticketStatusObj: TicketsStatusList = arrayTicketsListing[arrayTicketsListing.indexOf({ $0.status_id == "2" })!]
print(ticketStatusObj.status_name)
}
В то время как my arrayTicketsListing имеет значение [TicketsStatusList]
, содержит объекты класса TicketsStatusList
.
// TicketsStatusList class
class TicketsStatusList {
internal var status_id: String
internal var status_name: String
init(){
status_id = ""
status_name = ""
}
}
Ответ 5
Вот рабочий пример в Swift 3
class Point{
var x:Int
var y:Int
init(x:Int, y:Int){
self.x = x
self.y = y
}
}
var p1 = Point(x:1, y:2)
var p2 = Point(x:2, y:3)
var p3 = Point(x:1, y:4)
var points = [p1, p2, p3]
// Find the first object with given property
let firstPoint = points.first{$0.x == 1}
// Find all objects with given property
let matchingPoints = points.filter{$0.x == 1}
Ссылка: Закрытие закрытия