ios 开发Swift开发iOS

Swift十二讲 第三章 数组字典函数和闭包 (draft)

2015-01-31  本文已影响1184人  zydscience

1.数组

下面是几个声明数组的例子:

let a = [1,2,3] //整数数组,Swift可以自己推断出来类型
let m=a[0] //m被赋值为a的第一个元素,等于1
var b = ["x","y","z"]
var c = ["xx","yy"]
var d = b + c  
//数组可以做加法。不管数组是什么类型,加起来就是后一个附加于前一个的后面。不同类型的数组则不能相加。
var xx = [String](count: 2, repeatedValue: "x")

数组是值类型。传递的时候不是传递的地址或者索引,而是确实制造了一个拷贝。这点和Objective C的NSArray不同。

var a = [10,2,3]
println("\(a.sort { $0 < $1})") //输出[2,3,10]
println(a) //输出[2,3,10]; a被改变了
println("\(a.sorted{ $1 < $0})") //输出[10,3,2]
println(a) //sorted不改变原数组,输出还是[2,3,10]

sort算法执行后,原数组被改变。sorted算法执行后,返回一个排过序的数组。但原来的数组不变。

println("\(a.reverse())") //输出[2,3,10],原数组不变。

reverse顾名思义就是生成一个逆序数组。

println("\(a.filter {$0 > 2 })") //输出[3,10],原数组不变

filter返回满足一定条件的数组元素形成的新数组。filter的条件由一个closure定义。

println("\(a.map {$0 > 0 ? -$0 : 1 })")
//输出 [-2,-3,-10]

map返回数组的每个元素被map这个函数操作后的结果。函数由一个closure定义。

println("\(a.reduce(0) {$0 + $1 })")
//输出为15。

reduce返回一个值,这个值由reduce后面的closure给出。上例的意思是求数组所有元素之和。

数组一些有用的属性如下,意思都很直接易懂:

a.first
a.last //数组的第一个和最末一个元素
a.capacity //数组最多可以存多少个元素而无需后台重新分配内存
a.count //数组有多少个元素
a.isEmpty //数组是空的吗?

可以用下面代码替换数组的一部分元素:

a[1...2] = [2,3] //数组的第二第三个元素被替换为[2,3]

可以用下面代码去掉数组的单个指定元素:

a.removeAtIndex(1)
println(a) //数组的第二个元素被去掉。

可以用下面代码确保数组被分配了足够的内存而不用后台重新调动。

a.reserveCapacity(10) // 预定了够放10个元素的内存。

2.字典

字典的类型的形式定义为Dictionary <KeyType:ValueType>。可以简写为[Keytype:ValueType]。字典其实就是两个数组放在一起,第一个数组是索引,第二个是值。因此,第一个数组不能有重复的值。例如下面句子会报错:

let aa = [1:2, 1:3]

Playground会告诉你:
“fatal error: dictionary literal contains duplicate keys”

另外,既然Key和Value都类似于数组,Key的元素必须是同类型的。Value也必须同类型。

字典的初始化可以指定类型,也可以指定一些初始值,然后编译器会做类型推断。例如:

var a = ["狗有几条腿":4,"人有几条腿":2]
var b: [String:String] = ["狗":"白色","兔子":"灰色"]

你还可以不指定初始值,只是给出其最小容量。或者定义一个空字典。

 var c = [String:String]() 
 var d = [String:String] (minimumCapacity:2)

字典的value部分可以用key来索引到:

println(a["狗有几条腿"]!)  //输出为4

可以定义个一个数组,其值为字典的value部分或者key部分。

var ax = [String](a.keys)
println(ax)
var ay = [Int](a.values)
println(ay)
//注意这里必须指定类型;得到的数组的次序未必就是字典的原来顺序。
//字典是以key为索引的,其元素的位置无意义。

字典也有.count,.isEmpty等类似于数组的属性。

3.定义在数组或者字典上的循环

定义在数组上的循环的格式为:

for item in my_Array
{
 //在这里item被当作常量使用。
//第一次进入循环,item的值是my_Array的第一个值,第二次入循环是数组的第二个值。等等。
//item不能被修改。   
}

例如:

var a=["方","圆","三角"]
for i in a
{
    println(i)
}  //依次输出方圆三角

定义在字典上的循环的格式为:

for (key, value) in my_Dict
{
 //在这里(key,value)被当作常量使用。
//第一次进入循环,的值是my_Dict的第一个值,第二次入循环是数组的第二个值。等等。
//(key,value)不能被修改。   
}

你可以直接定义一个定义在字典的keys上的或者values上的循环

    for my_key in my_Dict.keys
    {
    //my_key是常量,不能修改。每次入循环,自动被赋予下一个keys的值
    }

    for my_value in my_Dict.values
    {
    //my_value是常量,不能修改。每次入循环,自动被赋予下一个values的值
    }

4.函数

Swift的函数和闭包定义和用法是非常丰富的。就算是编程专家,也很难一时掌握好。我们要做的是,化繁为简。只重点阐述用起来肯定不会有问题的,强大的有用的那些部分。

调用函数:

函数名(外部参数名:参数值)
var ii=24
func ad3(x:Int)->Int
{return x+30}
println(ad3(ii)) //输出54

套用上面模版,一些例子如下:

var i = 32
var ii = 24

func ad1(var # x:Int)->Int{
x = x+5
return x}

let b = ad1(x: ii)
println(b) //输出29 
println(ii)  //输出24

func ad2(inout i:Int)->Int{
i=i+20
return i+20}

var a = ad2(&i)
println(i) //输出52
println(a) //输出72

如上例所示。如果想要在函数体之内改变函数体之外一个变量的值,只能用inout。

func ad3(x: Int...)->Int
{return x[1]+30}
println(ad3(30,-1)) //输出29
func ad1(var # x:Int)->Int{
x = x+5
return x}
func ad4(x: Int, # myFunc: (Int)->Int)->Int
{
println("结果="+"\(myFunc(x))")
return 0
}
//输出 "结果=7"
//函数ad4的一个参数是类型为(int)->int的函数。
//函数ad1符合这个类型,所以可以传进去执行。

5.闭包

这里只简单介绍下闭包。一来因为目前用处并不广泛。二来Swift说不定会改语法或者扩展语法。我建议读者自行试验和写一些常用的闭包,存起来日后用。不要使用没有仔细分析和试验过的闭包。

例如:

let animals = ["狗", "猫", "兔"]
let myexample = animals.map({
(x: String) -> String in
"\(x)长大了"+"长大了"
})

println(myexample)
//输出为
//[狗长大了长大了, 猫长大了长大了, 兔长大了长大了]

再比如你想把一个数组的每个元素都平方下:

var xx = [1,2,3]
let b = xx.map({$0 * $0})
println(b) //输出[1,4,9]
//是不是像matlab一样简单?

最后关于所谓的函数式编程吐两句槽。Lambda Calculus是丘奇在古代的伟大发明。学会函数式编程,可以增广见闻,或许在某些场合有用,也或许某天函数式编程会成为主流。但这个东西就和学会用对数表算乘法区别不大。并没有特别神秘之处。发明东西难。学会东西容易。切忌因为会个特殊的语法糖,而时时去用这个语法糖来彰显自己的不同之处,那样会造成项目灾难。

(当然,如果你真的发明了一个类似于函数编程之类的东西,别忘了告诉我。)

上一篇下一篇

猜你喜欢

热点阅读