集合

集合的定义

Swift中提供了两种数据结构用于存放数据的集合,各自是数组(Array)和字典(Dictionary)。

他们的主要差别在于数组中的元素由下标确定。而字典中的数据的值由数据的键(Key)决定。下面我们觉得集合就是数组或字典。

集合的可变性

我们能够定义一个集合常量或者集合变量。

一旦定义为常量,就意味着集合的长度、内容和顺序都不能再改动了。比方,定义为常量的数组,不能再向当中加入新的元素。

数组的创建

由于swift中变量的创建遵循“ var 变量名:变量类型 ”的语法。因此数组的创建归根结底还是数组类型的定义。

一共同拥有三种方法来定义数组的类型:

var arrayOne:Array<Int> = [1,2,3]
println("arrayLong = \(arrayOne)") var arrayTwo:[Int] = [1,2,3]
println("arrayShort = \(arrayTwo)") var arrayThree = [1,2,3]
println("arrayThree = \(arrayThree)")

第一种是数组类型的完整定义,即Array关键字加上一对尖括号,括号内写上数组元素的类型。

另外一种是数组类型的简化定义,即一对方括号内写上数组元素的类型。这与第一种定义方法全然等价。

在使用这两种方法定义数组的时候。一定要确保数组中每一个元素类型同样,否则将会产生编译错误。

第三种运用了Swift的类型推导的特性。须要注意的是。数组的值由方括号组成,里面的元素用逗号隔开。假设方括号改成了圆括号。编译器不会报错(这将变成元组),所以千万要小心,避免莫名其妙的错误。

第三种方法除了书写简单之外,另一种优点,即不必确保数组中每一个元素类型同样。我们来通过代码看一看多个不同类型的元素出如今统一数组中会发生什么情况:

var arrayThree = [1,2,3]
println("arrayThree = \(arrayThree)") var arrayMixed = [1,"abc",true, 1.5]
println("arrayMixed = \(arrayMixed)")//在这一行结束前设置断点
//在LLDB调试当中分别输入print arrayThree和print arrayMixed

能够得到例如以下结果

([Int]) $R0 = 3 values {
[0] = 1
[1] = 2
[2] = 3
} ([NSObject]) $R1 = 4 values {
[0] = 0x0000000000000137 Int64(1)
[1] = "abc"
[2] = 0x00007fff7255e8a8 {
NSNumber = {
NSValue = (null)
}
}
[3] = 0x00000001006008a0 {
NSNumber = {
NSValue = (null)
}
}
}

因此不难发现,arrayMixed数组之所以能够加入多个类型的元素,是由于它被推导为Array< NSObject>类型。同样的,所以一旦数组的类型确定。就不能再插入不属于这个类型的的值。

在我阅读的教材上,作者特别提出。不指定类型的数组不能使用Array的append方法。

可是经过我的測试。并没有这种限制。有兴趣的读者能够自行測试,欢迎指正。

数组的訪问与改动

数组长度

能够使用数组的仅仅读属性count来获取数组长度:

var arrayThree = [1,2,3]
println("arrayThree.count = \(arrayThree.count)")

推断数组为空

能够使用数组的仅仅读属性isEmpty来推断数组是否为空。当然通过推断count是否为0也能够达到同样的效果,只是代码略长一些。

var arrayThree = [1,2,3]
if !arrayThree.isEmpty{
println("Array Three is not empty")
}

加入新元素

一共同拥有两种方法能够在数组的尾部加入新元素:

//方法一,使用数组的append函数
var arrayThree = [1,2,3]
arrayThree.append(4)
println("arrayThree = \(arrayThree)") //方法二。使用加法运算符
var arrayThree = [1,2,3]
arrayThree += [4]
println("arrayThree = \(arrayThree)")

不管使用哪种方法,都必须保证新加入的元素和数组类型同样。

比方试图像arrayThree中加入元素’1.5’会导致编译错误。

能够看到,另外一种方法的本质实际上是在两个数组对象之间调用加法运算符,得到的结果是两个数组拼接之后的结果。

因此,另外一种方法具有一个强大的功能,即向数组尾部加入多个元素。

另一种通用的方法,即调用数组的insert(atIndex:)方法。在指定位置插入新元素。

var arrayThree = [1,2,3]
arrayThree.insert(4, atIndex: 2)
println("arrayThree = \(arrayThree)")

删除数组元素

能够调用数组的removeAtIndex()和removeLast()方法。

var arrayThree = [1,2,3]
var numberThree = arrayThree.removeAtIndex(2)
var numberTwo = arrayThree.removeLast()

这两个方法会返回被删除的元素的值,当然假设不须要知道,能够无视它的返回值,直接调用方法就可以。

须要注意的一点是,removeAtIndex方法首先要推断下标是否越界。也就是说它会用到数组的长度。这意味着须要线性遍历数组。因此假设仅仅须要移除数组的最后一个元素且数组长度非常大时。应该使用removeLast()方法。

訪问数组元素

了解了怎样加入和删除元素。我们就要想办法把新加入的元素取出来看看了。通过数组下标能够訪问指定位置的数组元素,语法与C语言同样。

var arrayThree = [1,2,3]
println("ArrayThree[2] = \(arrayThree[2])")

改动数组元素

下标不仅能够訪问数组元素。还能够实现数组元素的改动。

这和訪问数组元素是非常相似的,仅仅要交换等号两边变量的位置就可以。

var arrayThree = [1,2,3]
var secondInt = arrayThree[1] //訪问元素 var newSecond = 4
arrayThree[2] = newSecond //改动数组元素

不仅如此,还能够通过数组下标批量改动元素:

var arrayThree = [1,2,3]
var firstNumber = 1
var secondNumber = 2
arrayThree[0...1] = [firstNumber,secondNumber]

此时,等号的右側必须是数组的字面量,而不能是一个数组变量。

也就是说这种写法是错误的:

var arrayThree = [1,2,3]
var newArray = [3,4]
var newSlice: ArraySlice<Int> = [3,4]
arrayThree[0...1] = newArray //错误。 arrayThree[0...1] = newSlice //正确

原因是左边的arrayThree[0…1]事实上是一个SubArray,在Swift中它的类型叫做ArraySlice。即Int类型的数组切片,而右边是一个Array类型变量,依据Swift类型安全的特性,这种操作自然是被禁止的。

假设左边的切片长度和右边的变量长度不一致会发生什么情况呢?不用过于操心,这不会产生不论什么错误。Swift会机智的帮我们解决问题。

var arrayOne:[Int] = [1,2,3]
var arrayTwo = [1,2,3]
var sliceOne:ArraySlice<Int> = [1,2,3]
var sliceTwo:ArraySlice<Int> = [1]
arrayOne[1...2] = sliceOne
arrayTwo[1...2] = sliceTwo
println("arrayOne = \(arrayOne)")
println("arrayTwo = \(arrayTwo)")

输出结果各自是:

arrayOne = [1, 1, 2, 3]
arrayTwo = [1, 1]

因此。假设变量长度超过切片长度,将会自己主动在切片位置后加入元素(如同arrayOne),相当于调用了数组的insert(atIndex:)方法若干次。同样地,假设变量长度少于切片长度,没有值的位置的元素自己主动被移除,后面的元素自己主动向前补上。相当于调用了数组的removeAtIndex()方法若干次。

尽管这样不会出现不论什么错误,只是出于逻辑严谨性考虑,应该避免等号两端变量长度不一样的情况。

数组遍历

之前我们介绍了数组的增删改操作,还缺少一个查找。

也就是数组的遍历。

在Swift中,除了像C语言那样定义一个下标变量,在for循环中遍历数组,还有两种方式遍历数组。

//方法一,使用for in循环高速遍历
var array = [1,2,3,2,1,32,99]
for number in array{
println("number = \(number)")
}

通过观察输出结果能够发现。for in循环是依照从前向后的顺序遍历数组的。

//方法二:使用enumerate函数
var array = [1,2,3,2,1,32,99]
for (index, value) in enumerate(array){
println("value = \(value)")
}

enumerate(array)方法的返回值是一个数组。数组中的每一个元素都是一个二元元组。第一个值是下标index。第二个值是元素的值。这个方案也是顺序遍历数组。

数组的初始化

在本章的开头。我们利用数组字面量来初始化一个数组。事实上,数组还有其它的初始化方法。

首先类比字符串的构造方法var string = String(),我们能够得知数组的另外两种构造方法。

var arrayOne = [Int]()
var arrayTwo = Array<Int>()
println("第一个数组元素个数为:\(arrayOne.count)")
println("第二个数组元素个数为:\(arrayTwo.count)")

执行结果:

第一个数组元素个数为:0
第二个数组元素个数为:0

除此以外,数组另一种特殊的构造方法,能够指定数组长度,在这种情况下还必须强制指定数组中每一个元素的值。

假设觉得无用的话。能够先设置为0,然后再改动。

var arrayThree = [Int](count: 5, repeatedValue: 0)
var arrayFour = Array<Int>(count: 5, repeatedValue: 0)
var arrayFiver = Array(count: 5, repeatedValue: 0)
print("第三个数组为:\(arrayThree)")
print("第四个数组为:\(arrayFour)")
print("第五个数组为:\(arrayFiver)")

得益于类型推导,第五种数组初始化方法也是合法的。

可是之前的标准初始化方法不能够这么简化。输出结果例如以下:

第三个数组为:[0, 0, 0, 0, 0]
第四个数组为:[1, 1, 1, 1, 1]
第五个数组为:[2, 2, 2, 2, 2]

附录

查看完整专栏——《Swift轻松入门》

【Swift入门(一)——基本的语法】

【Swift入门(二)——字符与字符串】

【Swift入门(三)——元组(Tuple)】

【Swift入门(四)——可选类型(Optionals)与断言(Assert)】

【Swift入门(五)——数组(Array)】

【Swift入门(六)——字典(Dictionary)】

【Swift入门(七)——结构体(Struct)】

【Swift入门(八)——功能强大的求余运算符】

【Swift入门(九)——String与Int、Double、Float等数字相互转换】

【Swift入门(十)——循环引用、弱引用和无主引用】

【Swift入门(十一)——类型转换与is、as操作】

【Swift入门(十二)——利用Extension加入逆序输出字符串方法】

Swift入门(五)——数组(Array)的更多相关文章

  1. Javascript入门(五)数组操作、循环语句

    一.数组与数组操作 <script type="text/javascript"> //数组定义方式 var list1 = new Array(1,2,3); var ...

  2. Swift 4.0 数组(Array)之过滤器(filter)的使用

    我们先来定义一个常量整型数组 let array = [5, 4, 3, 1, 2] 过滤器(filter)使用之筛选出大于3的值 let resultArray = array.filter { ( ...

  3. Swift 4.0 数组(Array)学习

    定义数组常量(常量只有读操作) let array1: [Int] = [11, 55, 5] let array2 = [11, 55, 5] 定义数组变量 var array: [Int] = [ ...

  4. Swift语法基础入门二(数组, 字典, 字符串)

    Swift语法基础入门二(数组, 字典, 字符串) 数组(有序数据的集) *格式 : [] / Int / Array() let 不可变数组 var 可变数组 注意: 不需要改变集合的时候创建不可变 ...

  5. [Swift]数组(Array)最强解析

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. swift基本用法-数组array

    数组简单用法 //------------------------------------------------------------------------------ // 1. 数组定义 / ...

  7. 学习Swift -- 数组(Array) - 持续更新

    集合类型--数组 Array是Swift中的一种集合类型:数组,数组是使用有序列表储存同一类型的多个值,与OC的NSArray的最大不同是,Swift的数组是值类型,OC的数组是引用类型 声明数组的方 ...

  8. [Swift]JSON字符串与字典(Dictionary)、数组(Array)之间的相互转换

    1.JSON字符串与字典(Dictionary)之间的相互转换 import Foundation //JSON字符串转换为字典(Dictionary) func getDictionaryFromJ ...

  9. Swift入门(一)——基本的语法

    近期開始学习swift.把学习的过程和总结整理成一个系列.方便日后回想总结. 基本的语法 基础语法 swift中每一行结束后不须要加分号.多个语句在同一行内须要用分好隔开 //表示凝视.或者用/* - ...

随机推荐

  1. Mac Os系统设置

    显示Mac隐藏文件的命令: defaults write com.apple.finder AppleShowAllFiles -bool true 隐藏Mac隐藏文件的命令:defaults wri ...

  2. 三星R428 内存不兼容金士顿2G DDR3

    京东上买了个金士顿2G DDR3, 回家装上之后发现不兼容, 原机带的是三星DDR3 1066的2G条子,买的是 金士顿DDR3 2G 1333的条子,结果单独插任何一根都好使,两个插槽均无问题,但是 ...

  3. python3 xpath数据获取案例

    import requestsfrom retrying import retryfrom lxml import etreeimport json class DaCheng(object): de ...

  4. webpack学习笔记啊(幕课)

    基础配置总结 webpack hello.js hello.bundle.js打包命令参数 --config filename : 指定其他名称做配置文件 --watch / -w : 监听文件改动, ...

  5. DIY 温控烙铁

    由于工艺原因,某处要使用200W大功率烙铁(恒温烙铁虽然有那么大功率,但没有那么大的烙铁头),只能选用普通电热丝烙铁(无温控),存在温度过高现象(造成工艺不良,同时因助焊剂+高温造成烙铁头腐蚀),逐渐 ...

  6. Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

    目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...

  7. python基础-------模块与包(二)

    sys模块.logging模块.序列化 一.sys模块 sys.argv           命令行参数List,第一个元素是程序本身路径 sys.exit(n)        退出程序,正常退出时e ...

  8. Python和Excel交互

    Python和Excel交互 使用的python包为XlsxWriter 下载的链接 https://pypi.python.org/pypi/XlsxWriter 初级的例子: def write_ ...

  9. 照虎画猫写自己的Spring

    从细节跳出来 看了部分Spring的代码,前面用了四篇内容写了一些读书笔记. 回想起来,论复杂度,Spring够喝上好几壶的.他就像一颗枝繁叶茂的大树,远处看,只是一片绿:走近看,他为你撑起一片小天地 ...

  10. 隐藏17年的Office远程代码执行漏洞(CVE-2017-11882)

    Preface 这几天关于Office的一个远程代码执行漏洞很流行,昨天也有朋友发了相关信息,于是想复现一下看看,复现过程也比较简单,主要是简单记录下. 利用脚本Github传送地址 ,后面的参考链接 ...