美文网首页
【Swift进阶笔记】内建集合类型-Set

【Swift进阶笔记】内建集合类型-Set

作者: BeethOven | 来源:发表于2021-11-06 11:13 被阅读0次
    image.png

    特征

    • 一组无序的元素,每个元素只出现一次
    • 通过哈希表实现的,集合中的元素必须满足Hashable
    • 遵守ExpressbilByArrayLiteral协议,也就是可以用数组字面量方式初始化一个集合
    let naturals: Set = [1, 2, 3, 2]
    naturals // [2, 1, 3]
    naturals.contains(3) // true
    naturals.contains(0) // false
    
    • 与其他类型集合一样,也支持我们那些已经见过的基本操作,如for, map ,filter等

    集合代数

    补集
    let iPods: Set = ["iPod touch", "iPod nano", "iPod mini",
    "iPod shuffle", "iPod Classic"]
    let discontinuedIPods: Set = ["iPod mini", "iPod Classic",
    "iPod nano", "iPod shuffle"]
    let currentIPods = iPods.subtracting(discontinuedIPods) 
    // ["iPod touch”
    
    交集
    let touchscreen: Set = ["iPhone", "iPad", "iPod touch", "iPod nano"]
    let iPodsWithTouch = iPods.intersection(touchscreen)
    // ["iPod touch", "iPod nano”
    
    并集
    var discontinued: Set = ["iBook", "Powerbook", "Power Mac"]
    discontinued.formUnion(discontinuedIPods)
    discontinued
    /*
    ["iPod shuffle", "iPod Classic", "iPod nano", "Powerbook",
    "iPod mini", "Power Mac", "iBook"]
    */”
    

    这里我们使用了可变版本的** formUnion**来改变原来的集合 (正因如此,我们需要将原来的集合用 var 声明)。几乎所有的集合操作都有不可变版本以及可变版本的形式,后一种都以 form 开头。想要了解更多的集合操作,可以看看 SetAlgebra 协议

    索引集合和字符集合

    SetOptionSet是标准库中唯一实现SetAlgebra的类型。在Foundation中这个类型也被IndexSetCharacterSet实现了。
    IndexSet 表示了一个由正整数组成的集合。当然,你可以用 Set<Int> 来做这件事,但是 IndexSet 更加高效,因为它内部使用了一组范围列表进行实现。打个比方,现在你有一个含有 1000 个元素的 table view,你想要一个集合来管理已经被用户选中的元素的索引。使用 Set<Int> 的话,根据选中的个数不同,最多可能会要存储 1000 个元素。而 IndexSet 不太一样,它会存储连续的范围,也就是说,在选取前 500 行的情况下,IndexSet 里其实只存储了选择的首位和末位两个整数值。

    不过,作为 IndexSet 的用户,你不需要关心内部实现,所有这一切都隐藏在我们所熟知的SetAlgebraCollection 接口之下,(除非你确实需要直接操作内部的范围,对于这种需求,IndexSet 通过 rangeView 属性暴露了一个它的视图出来,它是一个集合类型)。举例来说,你可以向一个索引集合中添加一些范围,然后对这些索引做 map 操作,就像它们是独立的元素一样:

    var indices = IndexSet()
    indices.insert(integersIn: 1..<5)
    indices.insert(integersIn: 11..<15)
    let evenIndices = indices.filter { $0 % 2 == 0 }
    // [2, 4, 12, 14]
    

    同样CharacterSet也是高效存储Unicode编码点(code point)的集合,常用来判断一个字符创是否包含某个子集(比如字母数字 alphanumerics 或者数字 decimalDigits) 中的字符。和 IndexSet 有所不同,CharacterSet 并不是一个集合类型,名字是从 Objective-C 导入时生成的

    属性 描述
    CharacterSet.alphanumerics 字母和数字的组合,包含大小写, 不包含小数点
    CharacterSet.capitalizedLetters 字母,首字母大写,Lt类别
    CharacterSet.decimalDigits 0-9的数字,也不包含小数点
    CharacterSet.whitespaces 空格
    CharacterSet.whitespacesAndNewlines 空格和换行
    CharacterSet.letters 所有英文字母,包含大小写 65-90 97-122
    CharacterSet.lowercaseLetters 小写英文字母 97-122
    CharacterSet.uppercaseLetters 大写英文字母 65-90
    CharacterSet.nonBaseCharacters 非基础字符 M*
    CharacterSet.illegalCharacters 不 合规字符,没有在Unicode 3.2 标准中定义的字符
    CharacterSet.punctuationCharacters 标点符号,连接线,引号什么的 P*
    CharacterSet.symbols 符号,包含S* 所有内容,运算符,货币符号什么的
    CharacterSet.newlines 返回一个包含换行符的字符集,U+000A ~ U+000D, U+0085, U+2028, and U+2029
    CharacterSet.symbols 符号,包含S* 所有内容,运算符,货币符号什么的
    inverted 相反的字符集。例如CharacterSet.whitespaces.inverted 就是没有空格
    // 去掉首尾空格
     let example =  " abc ".trimmingCharacters(in: CharacterSet.whitespaces)
     print(example)
    // abc
    
    //验证密码是否只包含数字
    let password = "123"
    print(password.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil)
    // true
    
    //url编码
      let url = URL(string: "http://www.api.test.com".addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)!)
    
    // 自定义
    let str2 = "#/%/<>?@"
    let custom = CharacterSet(charactersIn: "#").inverted
    let result = str2.addingPercentEncoding(withAllowedCharacters: custom) ?? ""
    print(result) //输出 %23/%/<>?@
    
    
    • CharacterSet.urlHostAllowed: 被转义的字符有 "#%/<>?@^`{|}
    • CharacterSet.urlPathAllowed: 被转义的字符有 "#%;<>?[]^`{|}
    • CharacterSet.urlUserAllowed: 被转义的字符有 #%/<>?@^`{|}
    • CharacterSet.urlQueryAllowed: 被转义的字符有 "#%<>[]^`{|}
    • CharacterSet.urlPasswordAllowed 被转义的字符有 "#%/:<>?@[]^`{|}

    CharacterSet.urlHostAllowed包含的是所有不需要被转码的字符,可以用两句代码验证:

    let unicode = "1".unicodeScalars.flatMap{ $0 }[0]
    print(CharacterSet.urlHostAllowed.contains(unicode)) //输出TRUE
    

    在闭包中使用集合

    extension Sequence where Element: Hashable {
    func unique() -> [Element] {
    var seen: Set<Element> = []
    return filter { element in
    if seen.contains(element) {
       return false
    
       } else {
             seen.insert(element)
             return true
           }
        }
      }
    }
    [1,2,3,12,1,3,4,5,6,4,6].unique() // [1, 2, 3, 12, 4, 5, 6]
    

    上面这个方法让我们可以找到序列中的所有不重复的元素,并且通过元素必须满足 Hashable 这个约束来维持它们原来的顺序。在我们传递给 filter 的闭包中,我们使用了一个外部的 seen 变量,我们可以在闭包里访问和修改它的值

    相关文章

      网友评论

          本文标题:【Swift进阶笔记】内建集合类型-Set

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