2015-11-03 55 views
2

使用以下代碼可以顯示如何使用Swift CollectionType .filter .indexOf .map實例方法在數組中查找值命名元組?Swift使用CollectionType .filter .indexOf和.map查找元組數組中的值

文檔here是不夠的。

import UIKit 
class Foo { 
    private var mData: String 
    init(data: String) { mData = data } 
    func printData() { print(mData) } 
} 
class ViewController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     var myList = [(code:Int64, list: [Foo])]() 
     let fooListA = [Foo(data: "A0"), Foo(data: "A1"), Foo(data: "A2")] 
     let fooListB = [Foo(data: "B0"), Foo(data: "B1"), Foo(data: "B2")] 
     let fooListC = [Foo(data: "C0"), Foo(data: "C1"), Foo(data: "C2")] 
     let fooListD = [Foo(data: "D0"), Foo(data: "D1"), Foo(data: "D2")] 
     myList.append((code: 10, list: fooListA)) 
     myList.append((code: 20, list: fooListB)) 
     myList.append((code: 30, list: fooListC)) 
     myList.append((code: 40, list: fooListD)) 

     // following lines cause errors  
     let foundItem: (code:Int64, list:[Foo]) = myList.filter { (Self.Generator.Element) -> Bool in 
      if item.code = 20 {return true} 
     } 
     foundItem.list[1].printData() // prints 'B1' 

     let foundItemIdx = myList.indexOf { (Self.Generator.Element) -> Bool in 
      if item.code = 20 { return true} 
     } 
     print(foundItemIdx) // prints '1' 

     // extra credit how does map work??? 
    } 
} 

回答

5

好了,有幾件事情錯了,讓我們通過分步:

filter返回對象的潛在集合 - 仍然是一個集合。因此,您不能將結果分配給(code:Int64, list:[Foo])類型的結果,而是[(code:Int64, list:[Foo])]。或者你一起省略顯式類型。

(Self.Generator.Element)是閉包中第一個參數的泛型類型。再次,你不必擔心它的類型,只寫參數的名稱 - >item

let foundItem = myList.filter { item -> Bool in 

在過濾你的內碼並不總是返回一個值 - 它只返回時滿足條件 - 你應該總是回報東西:

if item.code == 20 {return true}; return false 

這些聲明可以簡化爲

let foundItem = myList.filter { $0.code == 20 } 

在我開始寫的第一個陳述之後,你不能得到一個單一的項目,而是返回一個列表。再次

foundItem[0].list[1].printData() // prints 'B1' 

或稍多的功能:因此,你必須在數組中的特定索引訪問元素

foundItem.forEach { $0.list[1].printData() } 

另外,如果你只在第一個感興趣發現你可以寫:

let foundItem = myList.filter { $0.code == 20 }.first 
if let found = foundItem { 
    found.list[1].printData() // prints 'B1' 
} 

幾乎所有上述的(除了收集,東西)仍然是第二個「塊」真:

let foundItemIdx = myList.indexOf { $0.code == 20 } 

關於地圖:map讓你列表中的每個元素上執行的操作返回包含在列表中,而不是原始元素的操作的結果的列表:

let map2 = myList.map { $0.code/10 } 
let map3 = myList.map { $0.list[0].mData } 

print(map2) // [1, 2, 3, 4] 
print(map3) // ["A0", "B0", "C0", "D0"] 
1

感謝luk2302製作這很容易理解。對於那些尋找快速演示如何使用這些方法的例子,這裏是用Luk2302的解決方案重寫的代碼:

var myList = [(code:Int64, list: [Foo])]() 

let fooListA = [Foo(data: "A0"), Foo(data: "A1"), Foo(data: "A2")] 
let fooListB = [Foo(data: "B0"), Foo(data: "B1"), Foo(data: "B2")] 
let fooListC = [Foo(data: "C0"), Foo(data: "C1"), Foo(data: "C2")] 
let fooListD = [Foo(data: "D0"), Foo(data: "D1"), Foo(data: "D2")] 

myList.append((code: 10, list: fooListA)) 
myList.append((code: 20, list: fooListB)) 
myList.append((code: 30, list: fooListC)) 
myList.append((code: 40, list: fooListD)) 

// .filter - long way 
let foundItem = myList.filter { item -> Bool in 
    if item.code == 20 { 
     return true 
    } else { 
     return false 
    } 
} 
if let foundFirst = foundItem.first { 
    foundFirst.list[1].printData() // prints 'B1' 
} 

// .filter - short way 
if let foundItem = (myList.filter { $0.code == 20 }).first { 
    foundItem.list[1].printData() // prints 'B1' 
} 

// .indexOf - long way 
let foundItemIdx = myList.indexOf { item -> Bool in 
    if item.code == 20 { 
     return true 
    } else { 
     return false 
    } 
} 
if let foundItemIndexUnwrapped = foundItemIdx { 
    print(foundItemIndexUnwrapped) // prints '1' 
} 

// .indexOf - short way 
if let foundItemIdxShortWay = (myList.indexOf { $0.code == 20 }) { 
    print(foundItemIdxShortWay) // prints '1' 
} 

// map examples 
let map2 = myList.map { $0.code/10 } 
let map3 = myList.map { $0.list[0].mData } 

print(map2) // [1, 2, 3, 4] 
print(map3) // ["A0", "B0", "C0", "D0"]