美文网首页
Swift 4新功能 ------ 二(Whatʼs new

Swift 4新功能 ------ 二(Whatʼs new

作者: 阿丶布布 | 来源:发表于2017-06-17 01:26 被阅读39次

    Swift 4 新功能 -(二)

    1. 协议相关类型的约束
    2. 字典(Dictionary)和集合(Set)的增强
    3. MutableCollection.swapAt 方法
    4. reduce 和 inout
    5. 泛型下标
    6. NSNumber 桥接
    7. 类和协议的组合

    协议相关类型的约束

    SE-0142: 协议的相关类型可以用where语句约束. 看似一小步,却是类型系统表达能力的一大步,让标准库可以大幅简化. 喜大普奔的是, SequenceCollection 在Swift 4中用上这个就更直观了.

    • Sequence.Element

    Sequence 现在有了自己的相关类型Element . 原先Swift 3中到处露脸的Iterator.Element , 现在瘦身成Element:

    extension Sequence where Element: Numeric {
        var sum: Element {
            var result: Element = 0
            for item  in self {
                sum += item
            }
            return result
        }
    }
    [1,2,3,4].sum
    
    • 当扩展 Sequence 和 Collection 时所需约束更少
    // 在Swift 3时代, 这种扩展需要很多的约束:
    //extension Collection where Iterator.Element: Equatable,
    //    SubSequence: Sequence,
    //    SubSequence.Iterator.Element == Iterator.Element
    //
    // 而在Swift 4, 编译器已经提前知道了上述3个约束中的2个, 因为可以用相关类型的where语句来表达它们.
    extension Collection where Element: Equatable {
        func prefieIsEqualSuffix(_ n: Int) -> Bool {
            let head = prefix(n)
            let suff = suffix(n).reversed()
            return head.elementsEqual(suff)
        }
    }
    [1,2,3,4,2,1]. prefieIsEqualSuffix(2)
    

    字典(Dictionary) 和 集合(Set) 的增强

    SE-0165 加了一些很nice的 DictionarySet增强.

    • 基于序列(Sequence)的构造器

      从一个键值对序列构造字典.

    let hotLanguage = ["Swift", "Python", "Kotlin","JAVA","C++"]
    let hotLanguageRanking = Dictionary(uniqueKeysWithValues: zip(1..., hotLanguage))
    hotLanguageRanking[2]
    
    • 合并(merge)构造器 & merge 方法
      当从一个序列构造字典,或把一个序列合并到字典中,描述如何处理重复的键.
    let duplicates = [("a", 1), ("b", 2), ("a", 3), ("b", 4)]
    let letters = Dictionary(duplicates, uniquingKeysWith: { (first, _) in first })
    >>> letters = ["b": 2, "a": 1]
    
    

    合并构造器或 merge 方法遇到一个字典时就没那么舒服了. 因为字典的元素类型是一个 带标签的 元组型(key: Key, value: Value)但上述2个方法却要求一个 无标签的 元组型(Key, Value), 不得已要手工转换. 希望这个今后能完善. 见 SR-922 SR-4969.

    let defaults = ["foo": false, "bar": false, "baz": false]
    var options = ["foo": true, "bar": false]
    // 会产生一个烦人的类型转换警告 
    // error: error: generic parameter 'S' could not be inferred
    options.merge(defaults) { (old, _) in old }
    // 替代方法
     options.merge(defaults.map { $0 }) { (old, _) in old }
    
    • 下标的默认值

    你现在可以给下标中加一个默认值参数, 当key不存在时会返回这个值, 这样便可让返回类型非Optional.

    hotLanguage[4, default: "(unknown)"]
    

    在你想通过下标更新一个值时,这个功能就非常有用:

    let source = "how now brown cow"
    var frequencies: [Character: Int] = [:]
    for c in source {
        frequencies[c, default: 0] += 1
    }
    frequencies
    
    
    var words = """
        天姥连天向天横 势拔五岳掩赤城
        天台四万八千丈 对此欲倒东南倾
        我欲因之梦吴越 一夜飞度镜湖月
        湖月照我影 送我至剡溪
        """
    var frequencies: [Character: Int] = [:]
    for word in words.components(separatedBy: .whitespacesAndNewlines).joined() {
        frequencies[word, default: 0] += 1
    }
    for (word , count) in frequencies {
        if count > 1 {
            print(word, count)
        }
    }
    
    • Dictionary相关的 map 和 filter

    filter 返回一个 Dictionary 而非 Array. 相似的, 新方法mapValues转换值的同时保持字典结构.

    let filtered = hotLanguageRaking.filter {
        $0.key % 2 == 0
    }
    type(of: filtered)
    
    let mapped = hotLanguageRanking.mapValues { value in
        value.uppercased()
    }
    mapped
    
    
    • Set.filter 现在同样返回一个Set而不是 Array
    let set: Set = [1,2,3,4,5]
    let filteredSet = set.filter { $0 % 2 == 0 }
    type(of: filteredSet)
    
    • 分组一个序列

    把一个序列分成几组, 比如联系人按姓分组.

    let contacts = ["Julia", "Susan", "John", "Alice", "Alex"]
    let grouped = Dictionary(grouping: contacts, by: { $0.first! })
    >>> grouped = ["J": ["Julia", "John"], "S": ["Susan"], "A": ["Alice", "Alex"]]
    
    

    MutableCollection.swapAt 方法

    SE-0173 介绍了一种交换一个集合中两个元素的新方法. 与既有的 swap(_:_:)方法不同, swapAt(_:_:)接受一个要交换的元素切片, 而不是整个元素本身 (通过 inout 参数).

    加这个的目的是 swap 方法带2个inout 参数 不再兼容新的独占式内存访问规则,见SE-0176. 既有的 swap(_:_:)方法不能再交换同一个集合中的两个元素.

    var numbers = [1,2,3,4,5]
    numbers.swapAt(0,1)
    // Swift 4中非法
    //swap(&numbers[3], &numbers[4])
    //numbers
    
    

    reduce 和 inout

    SE-0171 新增reduce的一个变体, 让部分结果以inout传递给组合函数. 如此一来可以通过消除中间结果的副本来递增一个序列,大幅提升reduce算法的性能.

    SE-0171 未实现.

    // 尚未实现
    //extension Sequence where Element: Equatable {
    //    func uniq() -> [Element] {
    //        return reduce(into: []) { (result: inout [Element], element) in
    //            if result.last != element {
    //                result.append(element)
    //            }
    //        }
    //    }
    //}
    //[1,1,1,2,3,3,4].uniq()
    

    Swift 4 新功能 -(一)

    英文 By Ole Begemann 中文 by 小波
    相关视频

    相关文章

      网友评论

          本文标题: Swift 4新功能 ------ 二(Whatʼs new

          本文链接:https://www.haomeiwen.com/subject/jskvqxtx.html