Swift使用CollectionType .filter .indexOf和.map查找元组数组中的值

时间:2015-11-03 20:41:12

标签: ios arrays swift tuples

使用以下代码,您可以展示如何使用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???
    }
}

2 个答案:

答案 0 :(得分: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: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 :(得分: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"]