2014-09-27 62 views
41

是否有可能從具有特定屬性的數組中獲取對象?或者我需要循環槽中的所有對象,並檢查屬性是否是我正在尋找的具體內容?使用數組中的屬性查找對象

編輯:感謝您給我正確的方向,但我有一個問題來轉換這一點。

//再次編輯:好的,如果只有一個特定的結果?這也是一個可行的方法嗎?

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 }) 

回答

90

更多信息//這是行不通的 - 的NSArray不是圖像 - 的一個亞型,所以如果有什麼,只有1個可能的結果呢?

你沒有辦法在編譯時證明數組只有一個可能的結果。你實際要求的是第一個匹配結果。最簡單的(雖然不是最快的),是隻取過濾的結果的第一個元素:

let imageObject = questionImageObjects.filter{ $0.imageUUID == imageUUID }.first 

​​現在將是一個可選的課程,因爲它可能是沒有匹配。

如果搜索整個數組非常耗時,當然,您可以輕鬆創建一個函數,該函數將返回與閉包匹配的(可選)第一個元素,但對於較短的數組,這很好而且簡單。


查爾斯指出,在斯威夫特3這是建於:

questionImageObjects.first(where: { $0.imageUUID == imageUUID }) 
+0

您可以在中間添加'lazy'函數,所以它應該只掃描數組直到第一個匹配,並避免你正確地提到的性能問題:'let imageObject = questionImageObjects.lazy.filter {$ 0.imageUUID == imageUUID} .first' – charles 2017-01-20 15:04:19

+6

其實,'questionImageObjects.first(其中:{$ 0.imageUUID == imageUUID})'是可能是快速前進的方式3 – charles 2017-01-20 15:06:38

9

是的,你可以使用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返回含有滿足邏輯表達式的所有項的數組。在Library Reference

+0

您還可以使用NSPredicate,並使用一個NSArray。 – 2014-09-27 10:38:03

+0

如何過濾firstName和lastName? – Kaptain 2016-12-01 11:47:27

+1

@Kaptain:這應該很簡單:用'return $ 0.firstName ==「John」&& $ 0.lastName ==「Doe」'替換'return $ 0.firstName ==「John」'。換句話說,簡單地重寫/擴展傳遞給過濾器的閉包,確定何時應該包含元素 – Antonio 2016-12-10 16:53:39

29

編輯2016年5月5日:斯威夫特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}) 
1

這是其他方式使用對象屬性來搜索數組的對象來獲取特定對象。

if arrayTicketsListing.contains({ $0.status_id == "2" }) { 
     let ticketStatusObj: TicketsStatusList = arrayTicketsListing[arrayTicketsListing.indexOf({ $0.status_id == "2" })!] 
     print(ticketStatusObj.status_name) 
} 

然而,我arrayTicketsListing是[TicketsStatusList]包含TicketsStatusList類的對象。

// TicketsStatusList class 

class TicketsStatusList { 
    internal var status_id: String 
    internal var status_name: String 
    init(){ 
     status_id = "" 
     status_name = "" 
    } 
} 
1

這裏是工作示例斯威夫特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} 

參考:Trailing Closure