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

2017-06-17  本文已影响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 . 原先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
// 在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增强.

let hotLanguage = ["Swift", "Python", "Kotlin","JAVA","C++"]
let hotLanguageRanking = Dictionary(uniqueKeysWithValues: zip(1..., hotLanguage))
hotLanguageRanking[2]
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)
    }
}

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

let filtered = hotLanguageRaking.filter {
    $0.key % 2 == 0
}
type(of: filtered)

let mapped = hotLanguageRanking.mapValues { value in
    value.uppercased()
}
mapped

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 小波
相关视频

上一篇下一篇

猜你喜欢

热点阅读