Найти объект с собственностью в массиве

Есть ли возможность получить объект из массива с определенным свойством? Или мне нужно зацикливать все объекты в моем массиве и проверить, является ли свойство конкретным, что я искал?

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}

Ссылка: Закрытие закрытия