Swift中,数组Array和字典Dictionary是用结构来实现的,但是数组与字典和其它结构在进行赋值或者作为参数传递给函数的时候有一些不同。

并且数组和字典的这些操作,又与Foundation中的NSArray和NSDictionary不同,它们是用类来实现的。

注意:下面的小节将会介绍数组,字典,字符串等的复制操作。这些复制操作看起来都已经发生,但是Swift只会在确实需要复制的时候才会完整复制,从而达到最优的性能。

字典的赋值和复制操作

每次将一个字典Dictionary类型赋值给一个常量或者变量,或者作为参数传递给函数时,字典会在赋值或者函数调用时才会被复制。这个过程在上面的小节:结构和枚举是数值类型中描述了。

如果字典中的键值是数值类型(结构或者枚举),它们在赋值的时候会同时被复制。相反,如果是引用类型(类或者函数),引用本身将会被复制,而不是类实例或者函数本身。字典的这种复制方式和结构相同。

下面的例子演示的是一个叫ages的字典,存储了一些人名和年龄的对应关系,当赋值给copiedAges的时候,里面的数值同时被完整复制。当改变复制了的数值的时候,原有的数值不会变化,如下例子:

var ages = ["Peter": 23, "Wei": 35, "Anish": 65, "Katya": 19] var copiedAges = ages

这个字典的键是字符串String类型,值是Int类型,都是数值类型,那么在赋值的时候都会被完整复制。

copiedAges["Peter"] = 24 println(ages["Peter"]) // prints "23"

数组的赋值和复制操作

和字典Dictionary类型比起来,数组Array的赋值和复制操作就更加复杂。Array类型和C语言中的类似,仅仅只会在需要的时候才会完整复制数组的值。

如果将一个数组赋值给一个常量或者变量,或者作为一个参数传递给函数,复制在赋值和函数调用的时候并不会发生。这两个数组将会共享一个元素序列,如果你修改了其中一个,另外一个也将会改变。

对于数组来说,复制只会在你进行了一个可能会修改数组长度操作时才会发生。包括拼接,添加或者移除元素等等。当复制实际发生的时候,才会像字典的赋值和复制操作一样。

下面的例子演示了数组的赋值操作:

var a = [1, 2, 3] var b = a var c = a

数组a被赋值给了b和c,然后输出相同的下标会发现:

println(a[0]) // 1 println(b[0]) // 1 println(c[0]) // 1

如果改变a中的某个值,会发现b和c中的数值也会跟着改变,因为赋值操作没有改变数组的长度:

a[0] = 42 println(a[0]) // 42 println(b[0]) // 42 println(c[0]) // 42

但是,如果在a中添加一个新的元素,那么就改变了数组的长度,这个时候就会发生实际的复制操作。如果再改变a中元素的值,b和c中的元素将不会发生改变:

a.append(4) a[0] = 777 println(a[0]) // 777 println(b[0]) // 42 println(c[0]) // 42

设置数组是唯一的

如果可以在对数组进行修改前,将它设置为唯一的就最好了。我们可以通过使用unshare方法来将数组自行拷贝出来,成为一个唯一的实体。

如果多个变量引用了同一个数组,可以使用unshare方法来完成一次“独立”

b.unshare()

这时候如果再修改b的值,c的值也不会再受影响

b[0] = -105 println(a[0]) // 777 println(b[0]) // -105 println(c[0]) // 42

检查两个数组时候共用了相同的元素

使用实例相等操作符来判断两个数组是否共用了元素(===和!===)

下面这个例子演示的就是判断是否共用元素:

if b === c {     println("b and c still share the same array elements.") } else {     println("b and c now refer to two independent sets of array elements.") } // prints "b and c now refer to two independent sets of array elements."

也可以使用这个操作来判断两个子数组是否有共用的元素:

if b[0...1] === b[0...1] {     println("These two subarrays share the same elements.") } else {     println("These two subarrays do not share the same elements.") } // prints "These two subarrays share the same elements."

强制数组拷贝

通过调用数组的copy方法来完成强制拷贝。这个方法将会完整复制一个数组到新的数组中。

下面的例子中这个叫names的数组会被完整拷贝到copiedNames中去。

var names = ["Mohsen", "Hilary", "Justyn", "Amy", "Rich", "Graham", "Vic"] var copiedNames = names.copy()

通过改变copiedNames的值可以验证,数组已经被完整拷贝,不会影响到之前的数组:

copiedNames[0] = "Mo" println(names[0]) // prints "Mohsen"

注意:如果你不确定你需要的数组是否是独立的,那么仅仅使用unshare就可以了。而copy方法不管当前是不是独立的,都会完整拷贝一次,哪怕这个数组已经是unshare的了。

Swift学习笔记(12)--数组和字典的复制的更多相关文章

  1. swift学习笔记之---数组、字典、枚举、结构体

    1.数组-Array let types = ["none","warning","error"] //省略类型的数组声明 let menb ...

  2. 记录:swift学习笔记1-2

    swift还在不断的更新做细微的调整,都说早起的鸟儿有虫吃,那么我们早点出发吧,趁着国内绝大多数的coder们还没有开始大范围普遍应用. 网上有些大神说:swift很简单!我不同意这个观点,假如你用h ...

  3. Swift学习字符串、数组、字典

    一.字符串的使用 let wiseWords = "\"I am a handsome\"-boy" var emptyString = "" ...

  4. Swift学习笔记(5)--数组

    数组的下标从0开始计数,相关方法属性涉及到下标时也从0开始计数 1.定义: //1.可变数组 var cityArray = ["Portland","San Franc ...

  5. 学习笔记12—linux下文件的复制、移动与删除

    查看centOS 版本     cat /etc/redhat-release 1,复制粘贴文件 cp  [选项]  源文件或目录  目标文件或目录 2,剪切粘贴文件 mv [选项]  源文件或目录 ...

  6. matlab学习笔记12单元数组和元胞数组 cell,celldisp,iscell,isa,deal,cellfun,num2cell,size

    一起来学matlab-matlab学习笔记12 12_1 单元数组和元胞数组 cell array --cell,celldisp,iscell,isa,deal,cellfun,num2cell,s ...

  7. PHP学习笔记之数组篇

    摘要:其实PHP中的数组和JavaScript中的数组很相似,就是一系列键值对的集合.... 转载请注明来源:PHP学习笔记之数组篇   一.如何定义数组:在PHP中创建数组主要有两种方式,下面就让我 ...

  8. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  9. 【swift学习笔记】二.页面转跳数据回传

    上一篇我们介绍了页面转跳:[swift学习笔记]一.页面转跳的条件判断和传值 这一篇说一下如何把数据回传回父页面,如下图所示,这个例子很简单,只是把传过去的数据加上了"回传"两个字 ...

随机推荐

  1. HDU 5274(LCA + 线段树)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  2. python 统计文件top IP

    lines = ''' 1.2.2.3 1.21.29.19.... ''' cnt = {} for line in lines.split(): if line not in cnt: cnt[l ...

  3. [NOIP2015模拟10.27] [JZOJ4270] 魔道研究 解题报告(动态开点+权值线段树上二分)

    Description “我希望能使用更多的魔法.不对,是预定能使用啦.最终我要被大家称呼为大魔法使.为此我决定不惜一切努力.”——<The Grimoire of Marisa>雾雨魔理 ...

  4. Car Talk1

    This question is based on a Puzzler that was broadcast on the radioprogram Car Talk1: “I was driving ...

  5. 16.允许重复的multimap

    #include <iostream> #include <map> #include <cstring> using namespace std; void ma ...

  6. animation和transition做动画的区别

    animation做动画,是不需要去触发的,可以定义一开始就执行 transition做动画,是需要人为触发,才能执行的

  7. Android开发日志统一管理

    在开发中,我们通常要对日志的输出做统一管理,下面就为大家推荐一个日志输出类,在开发阶段只需将DEBUG常量设为true,生产环境将DEBUG设为false即可控制日志的输出.啥都不说了,需要的朋友直接 ...

  8. 滑动切换Activity代码

    最近需要对练习项目中的代码进行优化,发现很多代码写起来远比想象的困难很多.刚接触Android时间不长,很多东西都不能融会贯通,所以才会有这样的问题存在,当然学习中遇到的问题很有必要做个总结.想想这个 ...

  9. 2018年湘潭大学程序设计竞赛 Fibonacci进制

    Fibonacci数是非常有名的一个数列,它的公式为 f(n)=f(n-1)+f(n-2),f(0)=1,f(1)=2.  我们可以把任意一个数x表示成若干不相同的Fibonacci数的和, 比如说1 ...

  10. CF GYM 100781A(菊花图+直径)

    题目大意 给出若干颗树用最少的边把它们连成一个无向连通图,同时使图的直径最小.输出最小直径. 题解 我们定义树的半径为(树的直径+1)/2.符合题意的连接方式为.所有树的“中点”连在直径最长的树的中点 ...