集合类型

2018-03-04  本文已影响13人  痴人会说梦

Collection 类型

Collection Type

数组(Array),字典(Dictionary),集合(Set),都是以泛型结构体定义的,且不像Objective-c的mutable来表示其可进行修改,而是只有通过var声明的,才能对其进行增删改查,let声明的collection对象不仅不能改变它的值,也不能对其元素做添加,修改,删除等操作.

数组

存放相同类型的多个元素的有序线性列表,可以是任意类型,元组也可以,不允许出现不同类型的元素
数组的声明:
1.完整声明:Array<Element>,Element表示元素的类型
2.精简声明:[Element]
3.数组字面量:[value1,value2..]

//MARK:数组的声明

//完整声明
var array = Array<Int>()
//精简声明
let r = [Int]()

//5个元素,每一个都是3.0
let a = [Double](repeating:3.0,count:5)
let b = [(Int,Double)](repeating: (1,0.5), count: 3)

//数组字面量
var a1 = [1,2,3,4,5]

//数组不仅可以存放字面量,也可以存放其它常量或者变量
var a2 = [array,r,[2,3]]

//+操作符 将两个数组拼接在一起
var sumArr = a1 + [2,67,7]
sumArr

//通过下标访问操作符访问数组元素
print("first is \(sumArr[0])")

//下标不可以使用负数,当然你可以自己进行定义
//超出数组的下标范围,程序会引发异常
//Fatal error: Index out of range
//sumArr[-1]
//sumArr[20]

//下标操作符属于单目后缀操作符,它只有一个操作数。其操作数就是跟在它之前(即左侧)的后缀表达式,而下标中的表达式则不是它的操作数,这点请各位注意。此外,只有遵循了 Collection 协议的类型对象才能作为下标操作符的操作数。


//数组包含了多少个元素 Int类型的只读属性
a1.count

//判断数组是否为空,指的是是否包含元素,而不是是否为空值
r.isEmpty
a1.isEmpty

//判断数组是否包含某个元素,返回Bool类型
a1.contains(1)
a1.contains(6)

//在最后添加数组元素
a1.append(6)

//在指定的索引位置插入数组元素
a1.insert(12, at: 2)
a1

//删除数组元素(下标)
a1.remove(at: 1)
a1

//直接使用数组字面量是一个常量,无法对其进行修改


var array1 = [1,2,3,4,5]

print(array1.startIndex)
print(array1.endIndex)

if let i  = array1.index(of: 30) {
print(array1[i..<array1.endIndex])
}
array1.index(after: 5)

//访问range内的数组元素
array1[1...3]

//替换range内的元素为传入的collection
array1.replaceSubrange(1..<3, with: [20,30,40,50])
print(array1)

//弹出最后一个数组元素
array1.popLast()
print(array1)

//并不改变数组的值
array = Array(array1.dropLast())

print(array1)

集合Set

集合可以存放多个相同类型的元素
1.不允许出现相同的元素
2.无序不能通过下标进行访问
3.只有遵循Hashable的类型才能作为集合的元素
String,Int,Double,Float,Bool都遵循该协议

集合的完整类型Set<Element:Hashable>,Element表示集合元素的类型,没有精简表示法
也可以通过数组字面量进行创建,但必须通过类型标注申明为Set,否则会被编译器识别为Array

//创建一个集合类型为<Int>的空集合
var setA = Set<Int>()
//或者
setA = []
//不定参构造方法
setA = Set(arrayLiteral: 1,3,4,2,1,3)

//数组字面量
var setB:Set<Int> = [1,1,2,3,4]

//集合存放对象是根据其哈希值,不是根据下标(无序),所以需要保证存放的元素类型遵循Hashable
//访问 for-in || flatMap
for item in setA {
    print(item)
}
//元素的个数
setA.count
//是都包含元素
setA.isEmpty

setA.contains(1)

setA.insert(5)

setA.remove(1)

字典

以键值对的形式存放元素
特点:无序,键不允许重复,必须遵循Hashable;值可以是任意类型

完整形式Dictionary<Key:Hashable,Value>,key表示键的类型,value表示值的类型

精简表示法 [Key:Value]

//通过默认的构造方法创建一个空字典,类型为[String:Int]
var a = Dictionary<String,Int>()

//通过字典的不定参构造方法创建一个字典,使用元组来将字典的键值进行捆绑
//第一个元素为键,第二个元素为值
a = Dictionary(dictionaryLiteral: ("one",1),("two",2),("three",3))


//精简表示法
let b = [Int:Float]()
let c = [Int:Float](dictionaryLiteral: (1,1.1),(2,2.22),(3,3.333))

字典字面量

var a1:[String:Int] = [:]

a1 = ["one":1,"two":2,"three":3]

通过下标操作符进行访问,类型必须为键的类型
返回的是Optional,不存在就会返回nil

var a1 = ["one":1,"two":2,"three":3]
let four = a1["four"]
let one = a1["one"]

if let f = four {
print(f)
}else{
print("nil")
}

//根据键修改值
a1["one"] = 100

//或者根据实例方法,返回原来的值
a1.updateValue(1, forKey: "one")

//如果key存在就是修改,不存在则意味着新增
a1["four"] = 4

//根据key删除元素
a1.removeValue(forKey: "one")

//字典的个数
a1.count

//是否包含有元素
a1.isEmpty


//keys 属性的类型的是遵循 Collection 与 Equatable 协议的结构体类型;而 values 属性的类型则是遵循 MutableCollection 协议的结构体类型,它们与集合类型类似,不能通过下标方式访问其元素,而一般只能通过 for-in 循环迭代的方式逐一访问

for key in a1.keys{
print(key)
}

for value in a1.values {
print(value)
}

Range范围操作符

特点:Range 范围代表的是两个值的区间,它由上下边界进行定义,你可以通过..<来创建一个不包含上边界的半开范围,或者使用...创建同时包含上下边界的闭合范围.
应用:范围操作符可用于 for-in 循环迭代、获取一个数组的子数组、获取一个字符串的子串、case 语句中的区间匹配等场合

分别对应下面四种类型

元素满足
元素满足 (以整数为步长)

满足 半开范围 闭合范围
Comparable Range ClosedRange
Strideable CountableRange CountableClosedRange
//Range,CountableRange, ClosedRange, CountableClosedRange
let emptyRange = 0.0..<0.0
let singleDigitNumbers = 0..<10
let lowercaseLetters = Character("a")...Character("z")
let numbersRange = 1...10

范围操作符的左操作数必须小于等于右操作数,否则将会导致运行时异常
对于半开区间的范围操作符,如果左操作数等于右操作数,那么该范围是一个空区间
1.只有半开范围才能表达空区间的概念 (上下边界相等)
2.只有闭合范围能够包含它的元素类型所能表达的最大值

如果ClosedRange(闭区间范围操作符)的操作数是一个整数类型,那么该范围操作符的类型将是CountableClosedRange
如果Range(半开区间范围操作符)的操作数是一个整数类型,那么该范围操作符的类型将是CountableRange
ClosedRange和Range没有遵循Sequence协议,不能用for-in循环,而CountableRange和CountableClosedRange遵循了Sequence协议,可以用for-in迭代循环

Countable Range 可数范围 只有这类范围可以被迭代,类型的stride需要用整数进行约束,所以整数和指针类型是这类范围的有效边界值,但是浮点类型不是

使用

//for-in迭代循环
//CountableRange
for i in 1..<5 {
print(i)
}

//CountableClosedRange
for y in 1...5 {
print(y)
}

//如果是浮点数可以使用选择步长的
for a in stride(from: 4, to: 5, by: 0.1) {
print(a)
}
for b in stride(from: 3, through: 5, by: 0.2){
print(b)
}

//Type 'ClosedRange<Character>' does not conform to protocol 'Sequence'
//for item in lowercaseLetters{
//
//}

//获取数组的子数组
let array = [1,2,3,4,5,6]
//[3,4,5]
print(array[2...4])

//获取字符串的子串
let string = "abcdefghigk"
let strRange = string.startIndex ..< string.endIndex
print(string[strRange])

//case区间匹配
switch 3.0 {
case 0.0 ..< 2.0:
print("in 0.0 ..< 2.0")
case 2.0 ..< 4.0:
print("in 2.0 ..< 4.0")
default:
print("No in range")
}

//[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(singleDigitNumbers.map{$0 * $0})

实例属性与方法

/// - isEmpty:是否为空
/// - contains:是否包含某个值
/// - lowerBound:表示当前范围对象的下边界,一般都是范围操作符左操作数的值。
/// - upperBound:表示当前对象的上边界。这里无论是闭区间还是半开区间,上边界的值一般都是范围操作符的右操作数的值。
/// - isEmpty:表示当前范围是否为一个空范围,如果是空范围,那么该属性的值为 true,否则为 false。对于一个闭区间范围而言,它不会存在空范围,所以这个属性必定为 false。
/// - contains(_:):判断当前范围是否包含了指定的对象。
/// - overlaps(_:):判断指定的范围是否与当前范围对象存在叠交,只要两者有交集,那么就返回 true,否则为 false
/// - clamped(to:):裁减当前的范围到指定的区间范围内。

let doubleRange = 1.0 ... 3.0

print(doubleRange.lowerBound)
print(doubleRange.upperBound)

print("0..<0是否为空\((0..<0).isEmpty)")

print("range has 2.5 :\(doubleRange.contains(2.5))")

print("是否有交集:\(doubleRange.overlaps(2.0..<4.0))")

//裁剪 必须是闭合区间
let subsRange = doubleRange.clamped(to: 0.5 ... 2.0)
/// 1.0 ... 2.0
print(subsRange)

单边范围

单边范围操作符 (partial .部分的,不完全的 ,偏向一方的)
Swift4.0提供,只对范围操作符的一端设置操作数,另一端缺省
有三种类型

  1. a... 后缀单目操作符,表示从操作数开始的范围,大于等于a
  2. ...a 前缀单目操作符,表示以操作数为终点的范围,小于等于a
  3. ..<a 前缀单目操作符,表示以操作数为终点的范围,但不包括该数值,即小于a
    注意:操作符必须紧贴操作数
//CountablePartialRangeFrom
let countableFrom = 2...

//PartialRangeFrom
let from = 2.1...

//PartialRangeThrough
//
let throughs = ...2

//PartialRangeUpTo
let upTo = ..<2

使用:获取一个数组的子数组、获取一个字符串的子串

//使用单边范围获取数组的子数组,字符串的子串
let array = [1,2,3,4,5]
//[1,2,3]
print("...2:\(array[...2])")
//[3,4,5]
print("2..:\(array[2...])")
//[1,2]
print("..<2:\(array[..<2])")

//获取字符串后五个字符
let string = "abcdefghigk"
let strRange = string.index(string.endIndex, offsetBy: -5)...
print(string[strRange])

由于单边范围操作符不能表示一个有限范围的值,因此它不可能遵循Sequence协议,不能使用for-in
下面是一些方法

//2
countableFrom.lowerBound

//2
throughs.upperBound

//false
upTo.contains(2)
上一篇下一篇

猜你喜欢

热点阅读