/*
编程环境: xcode 7.0 beta6
*/
/*---------------------------一.数组的创建-------------------------*/
//[someType] 等同于 Array<someType>,都代表可以装有someType这种类型数据的数组,下边我只使用[someType]这种形式:
/*
1. 变量数组,常量数组:
变量数组可以进行更改,对应OC可变数组:NSMutableArray,常量数组不可以进行修改, 对应OC不可变数组:NSArray
*/
var arr1_1:[Int] //变量数组
let arr1_2: [Int] //常量数组,可以不直接赋值, 但是当第一次赋值过后就不可以更改了
/*
2. 数组的创建你可以指定这个数组装有什么类型,如果你指定特定的类型, 那么这个数组只能装这个类型的数据,或者这个类型的子类的数据;
*/
let arr1_3: [String] = ["ab","cd"] //只能添加字符串类型
/*
3. 如果你不指定的类型, swift会有类型推断,根据你在等号右边赋的值来进行类型推断:
*/
//(1). 如果赋的值都是某个特定类型的数据,比如说都是[1, 2, 3], 那么类型推断为[Int];
var arr1_4 = [1,2, 3] //这时arr1_4为[Int]类型
arr1_4 = [] //这种情况, arr1_4依旧是[Int]类型
//(2). 如果你所赋的值都为NSObject类的对象或者继承与NSObject类的对象,或者String, Int, Double等一些基础类型, 那么swift将这个数组推断为[NSObject]类型;
let NSStr1_1: NSString ="NSString"
let arr1_5 = [1,"123", NSStr1_1] //这时arr1_5为[NSObject]类型
//(3). 如果数组中包含不止继承与NSObject类的数据(没有任何继承与任何类的对象),或者不继承与NSObject又不是基础类型数据,比如说Array Dictionary, swift将其推断为NSArray类型(原来是OC中的类型, swift中一样有这个类型, 实现了部分OC中的方法), NSArray这个类型可以和swift中的[Element]相互转换, [Element](这个涉及到泛型, 就是一个占位类型, 你往数组添加任何类型的数据都可以);
let arr1_6 = [1,"123", arr1_5] //识别为NSArray类型
let arr1_7 = Array(arr1_6) //将其转换为[Element]类型,注意[Element]这个类型不可以直接声明;
/*如果想得到一个,空的泛型数组可以这样写:*/
let arr1_8 = [] //这个时候识别为NSArray类型
var arr1_9 = Array(arr1_8) //arr1_9就是一个空的[Element]类型的数组
//4. 创建一个有多个元素重复的数组
var arr1_10 = Array(count:3, repeatedValue: 1.3)
print(arr1_10)
/*打印结果
[1.3, 1.3, 1.3] //含有3个 1.3的数组
*/
//5. 通过两个数组相拼接的方式获取新数组
var arr1_11 = arr1_7 + arr1_9//等号后边两个数组必须是相同类型的数组,比如这两个都是泛型数组[Element]
print(arr1_11)
/*打印结果
[1, 123, (
1,
123,
NSString
)]
*/
//6. 通过 Array(arrayLiteral: <#T##Element...##Element#>)来创建数组:
var NSStr1_2: NSString ="NSString2"
let arr1_12 = Array(arrayLiteral:1, "123",1.23, NSStr1_2) //这后边只能填NSObject类的对象或者继承与NSObject类的对象,以及Int, Double, String 一些基础类型,这时arr1_12被识别为[NSObject]类型
//7. 通过范围运算符 0...1来创建数组:
//0...1 表示 0 到 1 的开区间(0..<1表示0 到 1 的半开半闭区间,不包括1)
let arr1_13 = [0,1, 2, 3, 4, 5]
var arr1_14 = arr1_13[0...3] //这个时候arr1_14为ArraySlice类型(ArraySlice类型和Array类型很像,像截取数组的一部分的时候, 都会被识别为ArraySlice类型,可以被理解为迷你版的Array, Array和 ArraySlice 类型和可以相互转换)
var arr1_15 = Array(arr1_14) //转换为Array<Int>类型
/*---------------------------二.遍历数组-------------------------*/
//1 首先说一下如何查看数组的元素,以及获取数组的一些基础属性
var arr2_1 = [999,10, 99, 4]
//(1)首先说一下数组名[下标]的方式来访问或者修改数组元素 eg:
print(arr2_1[0])
/*打印结果
999
*/
arr2_1[0] =110
print(arr2_1)
/*修改后的打印结果
[110, 10, 99, 4]
*/
//(2)通过0...1(这个表示0到 1 的开区间)的这种范围方式来访问数组:
print(arr2_1[0...1])
/*打印结果
[110, 10]
*/
//(3)获取数组某些特定位置的元素:
print(arr2_1.first) //获取数组的第一个元素 打印结果: Optional(110)
print(arr2_1.last) //获取数组的最后一个元素 打印结果: Optional(4)
//(4)获取数组元素的数量:
print(arr2_1.count) //打印结果: 4
//2. for in 数组遍历
//(1)for in 遍历全部元素
for id in arr2_1 {
print(id)
}
/*打印结果
999
10
99
4
*/
//(2)for in 遍历数组某一个区间的元素
for id in arr2_1[1...3]{
print(id)
}
/*打印结果:
10
99
4
*/
//3. for 循环数组遍历
for var i =0; i < arr2_1.count; ++i {
let id = arr2_1[i]
print(id)
}
/*打印结果
999
10
99
4
*/
//4. 使用枚举法,进行遍历
for (a, b) inarr2_1.enumerate(){
print("\(a) =\(b)")
}
/*打印结果
0 = 999
1 = 10
2 = 99
3 = 4
*/
//5. 模拟系统给出的枚举法遍历数组
var en = arr2_1.enumerate().generate()
var temp: (Int,Int)? = en.next()
while temp !=nil {
print(temp!)
temp = en.next()
}
/*打印结果
(0, 999)
(1, 10)
(2, 99)
(3, 4)
*/
/*---------------------------三.给数组添加元素-------------------------*/
//1. 在数组的后边添加一个元素
var arr3_1 = ["hello"]
arr3_1.append("world")
print(arr3_1)
/*打印结果:
[hello, world]
*/
//2. 在数组的某个位置添加元素:
arr3_1.insert("my", atIndex:1)
print(arr3_1)
/*
[hello, my, world]
*/
//3.使用 +=给数组拼接另一个数组: 在老版本是可以使用 +=拼接一个元素的, 但这个版本把这个功能去掉了
arr3_1 += ["codeWorm","dear"]
print(arr3_1)
/*打印结果:
[hello, my, world, codeWorm, dear]
*/
//4. 在数组的某个index位置,添加一个相同类型的数组:
arr3_1.insertContentsOf(["123","456"], at:0)
print(arr3_1)
/*打印结果:
["123", "456", "hello", "my", "world", "codeWorm", "dear"]
*/
/*---------------------------四.删除数组的元素-------------------------*/
var arr4_1 = [1,2, 3, 4, 5]
//1. 删除最后一个元素,返回值为被删除的元素
let remove1 = arr4_1.removeLast()
print(arr4_1)
/*打印结果
[1, 2, 3, 4]
*/
//2. 删除某个index的元素,返回值为被删除的元素
let remove2 = arr4_1.removeAtIndex(0)
print(arr4_1)
/*打印结果
[2, 3, 4]
*/
//3. 删除某个范围的元素
arr4_1.removeRange(Range(start:0, end: 1))
print(arr4_1)
/*打印结果
[3, 4]
*/
//4. 删除数组的所有元素,并且不保留数组所占的空间
arr4_1.removeAll()
//5. 删除数组的所有元素,但是所占的内存空间将被保留
arr4_1.removeAll(keepCapacity:true)
/*---------------------------五.修改数组的元素-------------------------*/
var arr5_1 = [1,2, 3, 4, 5, 6,7]
//1. 可以用数组名[下标数]这种形式 来修改某个index的元素值
arr5_1[0] =99 //将第0个元素的值修改为99
print(arr5_1)
/*打印结果
[99, 2, 3, 4, 5, 6, 7]
*/
//2. 将数组某个范围的元素替换为后面的这段数组的元素,注意这个范围最大数不能超过数组的count值 - 1否则会运行时崩溃
arr5_1[1...3] = [100,101, 102]
print(arr5_1)
/*打印结果
[99, 100, 101, 102, 5, 6, 7]
*/
//3. 使用 arr5_1.replaceRange(<#T##subRange: Range<Int>##Range<Int>#>, with: <#T##C#>) 来替换元素, 这里第一个参数为范围, 第二个参数是要替换的数组或者表示数组的指针
arr5_1.replaceRange(Range(start:0, end: 4), with: [0,1, 2, 3, 4])
print(arr5_1)
/*打印结果
[0, 1, 2, 3, 4, 5, 6, 7]
*/
//replaceRange 替换UnsafeMutableBufferPointer数组的指针类型:
var arr5_2 = [999,1000, 1001]
var pointer = UnsafeMutableBufferPointer<Int>(start: &arr5_2, count:arr5_2.count) //这是用来表示字符串的指针类型
arr5_1.replaceRange(0..<1, with: pointer) //第一个参数range的另一种表现形式, 0到 1 的半开半闭区间(0...1 表示0 到 1的开区间), 这里也就是表示, 将arr5_1的第0个元素替换成这个数组指针对应数组的元素
print(arr5_1)
/*打印结果
[999, 1000, 1001, 1, 2, 3, 4, 5, 6, 7]
*/
/*---------------------------六.对于数组的一些基础的判断-------------------------*/
//1. 判断数组是否为空
var arr6_1: [Int] = []
print(arr6_1.isEmpty)//判断的前提是数组已经被实例化
/*打印结果
true
*/
//2. 判断数组是否包含某个元素:
var arr6_2 = ["hello","world", "I","am", "code"]
//(1)可以直接这么调用:
print(arr6_2.contains("hello"))
/*打印结果
true
*/
//(2) 可以使用闭包为参数进行判断
let isContain =arr6_2.contains { (obj) -> Boolin //这个运行原理就是,编译器调用你的闭包,将数组内的元素顺次作为闭包的参数传入, 进行判断, 当然判断逻辑是你写的,直到闭包的返回值为true 或者将数组内的所有元素传参完毕闭包调用结束,否则继续传入下一个数组的元素作为参数调用这个闭包,如果闭包的返回值出现为true的情况,则contains返回值为true,如果直到闭包调用完毕都没有出现true的情况,则contains返回值为false
if obj == "木哈哈" {
return true
}
return false
}
//简写:
let isContainSam =arr6_2.contains{$0 =="木哈哈"} //$0 就是第一个参数的意思, $1第二个, 多个参数同理, 当一个闭包只有一个return语句时, return可以省略
print(isContain)
/*打印结果
false
*/
/*---------------------------七.数组分割为字符串, 字符串拼接数组-------------------------*/
//这个如果有OC基础就知道这个:
//1. 使用某个字符串来分割字符串,分割结果为数组:
let str7_1 = "www.baidu.com/www.v1.cn/haha"
let arr7_1 = str7_1.componentsSeparatedByString(".")
print(arr7_1)
/*打印结果
["www", "baidu", "com/www", "v1", "cn/haha"]
*/
//2. 使用NSCharacterSet类型来分割字符串:
let arr7_2 = str7_1.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString:"./")) //分别以.和 /来分割
print(arr7_2)
/*打印结果
["www", "baidu", "com", "www", "v1", "cn", "haha"]
*/
//3. 将数组拼接成字符串
let str7_2 = arr7_2.joinWithSeparator("我是 (空格)")
print(str7_2)
/*打印结果
www我是 (空格)baidu我是 (空格)com我是 (空格)www我是 (空格)v1我是 (空格)cn我是 (空格)haha
*/
/*---------------------------八.数组的一些其他方法-------------------------*/
//1. sortInPlace 排序
var arr8_1 = [2,32, 1, 5, 3, 4]
//sortInPlace方法就是原来的sort方法
arr8_1.sortInPlace { (id1, id2) ->Bool in //传入闭包的原理类似与将冒泡排序的排序准则传入,编译器来实现冒泡排序, 然后根据你的准则来判断是否交换元素位置, eg:
if id1 > id2{
return true
}
return false
}
//上边这个可以简写为:
//arr8_1.sortInPlace {$0 > $1} //$0 就是第一个参数的意思, $1 第二个, 多个参数同理,当一个闭包只有一个return语句时, return可以省略
print(arr8_1)
/*打印结果
[32, 5, 4, 3, 2, 1]
*/
//2. reverse 翻转数组:
let arr8_2 = [9,6, 3, 0, 2, 4,5]
let arr8_3 = Array(arr8_2.reverse())
print(arr8_3)
/*打印结果:
[5, 4, 2, 0, 3, 6, 9]
*/
//3. filter 过滤数组:
let arr8_4 = [-5, -4, -3, -2,0, 1, 2, 3, 4,5, 6, 7, 8]
let arr8_5 = arr8_4.filter{$0 %2 == 0 && $0 >0} //过滤出数组中的正偶数
//展开为:
//let arr8_5 = arr8_4.filter { (obj) -> Bool in
// return obj % 2 == 0 && obj > 0
//}
print(arr8_5)
/*打印结果:
[2, 4, 6, 8]
*/
//4. map 遍历计算数组
let arr8_6 = [1,2, 3, 4, 5]
let arr8_7 = arr8_6.map{$0 *2} //通过计算形成新数组
print(arr8_7)
/*打印结果:
[2, 4, 6, 8, 10]
*/
//5. reduce 方法
let arr8_8 = [2.0 ,9.0]
let result8_1 = arr8_8.reduce(9.0) { (obj1, obj2) ->Double in
return obj1/obj2
}
//reduce, 需要传一个初始值,这里传的是9.0, 第一次传入闭包两个参数分别为初始值本身和 数组的第一个元素,第二次传的两个参数分别为, 第一次闭包的运算结果和数组的第二个元素,直到所有数组的元素全部被运算完毕, 最后一次调用闭包完毕返回的值为最终的值, 这里做的计算也就是: 9.0/2.0/9.0 = 0.5
//简写为:
//let result8_1 = arr8_8.reduce(9.0){$0/$1} 这里涉及到尾随闭包的知识, 在网上搜一下尾随闭包就知道怎么回事了
print(result8_1)
/*打印结果:
0.5
*/
/*---------------------------九.数组拷贝-------------------------*/
/*
在swift刚一出现的时候,数组是作为引用类型出现的, 虽然作为一个结构体,但是更像是类的对象的性质, 这可见数组的这个结构体的底层不单单是像C语言和OC中在栈区开辟空间去存储值类型那么简单,猜测也是要去堆区开辟空间的, 在后来更新版本中, Array取消了这样的性质,而是只作为值类型出现, 这样就让新学习swift的人来说不会有"为什么值类型还可以做引用的操作?"这样的困惑, 下面是一个eg:
*/
var arr9_1 = [1,2, 3]
var arr9_2 = arr9_1
arr9_2[0] =999
print("arr9_1 =\(arr9_1) arr9_2 =\(arr9_2)")
/*打印结果:
arr9_1 = [1, 2, 3] arr9_2 = [999, 2, 3]
*/
//可见现在的数组是一个值类型了!