2015-04-18 35 views
6

雖然find(["a", "b"], "c")可以正常工作,但在嘗試查找內部結構的索引時出錯一個結構數組:Swift無法使用類型爲'([Score],Score)'的參數列表調用'find',其中Score是一個結構

struct Score 
{ 
    //... 
} 

var scores: [Score] = //... 
var score: Score = //... 

find(self.scores, score) // Error: Cannot invoke 'find' with an argument list of type '([Score], Score)' 

我雖然它可能是一個結構,不能相互比較默認情況下的問題。但是將Score的定義更改爲class 給了我同樣的錯誤。

+0

您已經找到原因。 'Score'必須實現'Equatable'協議(無論是結構還是類)。 –

+1

可能與此處相同的問題:http://stackoverflow.com/questions/27887387/how-to-use-contains-with-two-arrays-of-objects –

回答

14

編輯:作爲斯威夫特2。0,現在有一個內置版本find需要關閉,所以你不必自行編寫 - 而且,find已被重命名爲indexOf,現在是CollectionType的協議擴展,所以你稱它爲方法:

// if you make `Score` conform to `Equatable: 
if let idx = self.scores.indexOf(score) { 

} 

// or if you don't make it Equatable, you can just use a closure: 
// (see original answer below for why you might prefer to do this) 
if let idx = scores.indexOf({$0.scoreval == 3}) { 

} 

原始2.0之前的回答以下


雖然答案提示讓你Equatable類可以很好地工作,我建議你有點謹慎選擇做這個之前。原因在於,如文檔所述,可均等性意味着可替代性,並且您的運營商必須具有反身性,對稱性和傳遞性。如果你不堅持這一點,當使用equals,sort等算法時,可能會出現一些非常奇怪的行爲。如果在非final類中實現Equatable,請特別謹慎。如果你確定你可以滿足要求,那麼去做吧,find就可以。

如果沒有,你可以考慮是寫一個函數,應該是在標準庫,但不是,這是一個find,需要一個封閉的替代:

func find<C: CollectionType>(source: C, match: C.Generator.Element -> Bool) -> C.Index { 
    for idx in indices(source) { 
     if match(source[idx]) { return idx } 
    } 
    return nil 
} 

一旦你有這個,你可以提供你喜歡的任何匹配標準。例如,如果您的對象是類,則可以使用引用相等性:

let idx = find(scores) { $0 === $1 } 
+0

在Swift 3中似乎'indexOf'已經被重命名爲'index(of:)'。 – Pang

7

爲函數find是該接口/是:

func find<C : CollectionType where C.Generator.Element : Equatable>(domain: C, 
    value: C.Generator.Element) -> C.Index? 

這表示的CCollectionType必須是Equatable,此外元件,該value也必須是Equatable

[Note Swift 3.0:從Swift 3.0開始,您需要使用index函數,它有兩種變體。在第一個,你會提供你自己的斷言:

func index(where: (Self.Generator.Element) -> Bool) -> Self.Index? 

在第二,你的元素必須equatable:

// Where Generator.Element : Equatable 
func index(of: Self.Generator.Element) -> Self.Index? 

如果你決定去equatable路線,那麼以下適用。 注完]

Score結構是不Equatable,因此錯誤。 你需要弄清楚分數彼此相等意味着什麼。也許它是一些數字'分數';也許它是'分數'和'用戶ID'。這取決於你的Score抽象。一旦你知道,你使用實現==

func == (lhs:Score, rhs:Score) -> Bool { 
return // condition for what it means to be equal 
} 

注:如果您使用class,因此得分有「身份」,那麼就可以實現這個爲:

func == (lhs:Score, rhs:Score) -> Bool { return lhs === rhs } 

你用繩子例如工作,因爲StringEquatable。如果您在斯威夫特庫代碼看看你會看到:

extension String : Equatable {} 
func ==(lhs: String, rhs: String) -> Bool 
1

正如其他人所說的,你搜索的對象必須符合Equatable協議。

所以你需要一個擴展添加到您的分數結構,告訴它是否符合該協議的編譯器:

extension Score: Equatable {} 

然後你需要實現該類的==功能:

public func ==(lhs: Score, rhs: Score) -> Bool 
{ 
    return lhs.whatever == rhs.whatever //replace with code for your struct. 
} 
+0

爲什麼我在得到'Score'時得到同樣的錯誤一個'類'而不是?不是'=='對類有效嗎? – Rivera

+0

編號==不適用於任何自定義對象,除非您按照我的答案中所述定義它。 –

相關問題