刚刚开始学swift。其中有很大的改动
在接触到swift 的方法的时候,我想着写一个冒泡排序吧,在这个过程中我遇到了很多坑。
我按照其他语言的形式写了如下方法:
func sort(numbers:Array<Float>) -> Array<Float> {
var i = 0
var j = 0
for var tempFloat1 in numbers {
for var tempFloat2 in numbers{
if tempFloat2 > tempFloat1 {
tempFloat1 += tempFloat2
tempFloat2 = tempFloat1 - tempFloat2
tempFloat1 -= tempFloat2
}
j += 1
}
i += 1
}
return numbers
}
1、调用方法是的书写规则
我们较早的接触了实参和形参的概念。
我按照其他语言的样子写了这样一个方法,注意,这时 i,j 是没有意义的,因为swift 中没有平常那种的for循环,只有forin循环,我这样写方法,导致调用的时候我是一头雾水有了这样的提示和结果
按照我通常的理解,numbers作为实参,应该是让我手动输入的,怎么随着方法书写直接写出来了,后面Array<Float>
应该是要表示为数组类型吧我尝试了各种表示数组的类型,都直接报错了,不得以我查看了官方文档,文档中表示
By default, functions use their parameter names as labels for their arguments. Write a custom argument label before the parameter name, or write _ to use no argument label.
func greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
这就很明确了,有说明有例子, 使用 _ 或 on 符号,可以有效的避免这个问题,于是乎我修改了方法体,这样调用的时候看着就很顺眼了。
func sort(_ numbers:Array<Float>) -> Array<Float>
或
func sort(on numbers:Array<Float>) -> Array<Float> {
最后在调用的时候,如下
这看着就很顺眼了
写完方法之后我反应过来了,我这里形参和实参起同样的名字,给我带来了很大的困扰,如果不适用_或on也是可以直接调用的,把实参填到要输入的位置就可以了
2、forin循环的坑
forin循环会自动遍历数组中的每个元素。无需使用数组下标获取元素,
如上我定义了 tempFloat1
和tempFloat2
便利的值,但是在执行了之后却不是我想的那样的结果。
数组还是原来的数组,没有发生变化
我尝试打了无数个断点,推演了无数次,总觉得这个方法没有问题呀,两个变量的值也在发生变化。可是结果就是不变,这可头大了
于是乎,我猜想,forin生成的 这个中间变量真的可以改变吗?我做了一个最简单的尝试,如下
var numbers : [Float] = [7.8,3.99,2.01,7.55,4.02,6.41]
for var tempObj in numbers {
tempObj = 0.99;
}
随即 一个关于 tempObj 的警告出现了
Variable 'tempObj' was written to, but never read
它表示 tempobj 被写入,但从未被读取。再看看结果
数组并没有受影响,于是:一个结论产生了,*在每次for循环的过程中tempobj的值确实被修改了,但是并没有修改数组的元素。*因此这样的书写方式是不对的。
修改如下
var numbers : [Float] = [7.8,3.99,2.01,7.55,4.02,6.41]
var i = 0
for var tempObj in numbers {
tempObj = 0.99;
numbers[i] = tempObj
i += 1
}
这样就有效了
我们最终向修改数组元素的值
3、函数形参的不可变性
我想到了数组有一个 .swap方法,可以直接交换两个数组元素的值,这样就避免了使用交换变量值来交换的复杂设计。但是又遇到了如下问题
numbers 在方法体中,只起到一个值传递的作用,并不能改变他的值,说的直白点,就是 在方法体中,numbers 是let 类型的。
如果强制设置成var 就会有其他的报错。
如下
求两数的和,这里明确显示,不能改变num02 的值。
所以,我只能在方法体中定义一个var 类型来接受 形参,在去改变值了
4、forin循环数组变量的本质
假如 在一个forin循环中改变了数组元素的值,注意,不能改变数组的个数,例如: 在第一次循环中修改了第一个元素的值,那么在第二次循环中,中间变量的值是否会得到修改。我说的有点乱,请看例子
var numbers : [Float] = [7.8,3.99,2.01,7.55,4.02,10.41]
var i = 0
for tempObj in numbers {
if i == 1 {
numbers.swapAt(0, 4)
}
if i == 4{
print("还是原来的值...\(tempObj)")
}
i += 1
}
当 i == 1 时, 我交换了 第0 位 和第4 位的值,理论上来说,数组已经发生了变化,当i==4 时我期待,输出 7.8 可是结果还是输出了 4.02 如下图
这说明,在这个forin循环已开始,每次循环的这个中间变量值就已经分配好了,并不会随着数组元素值得改变而改变了
因此,在写选择排序时,需要在外层循环动态的改变这个中间变量的值。
最终,写好了这个排序算法。
代码如下 当然还有可优化的地方
func sort(on numbers:Array<Float>) -> Array<Float> {
var targetArr = numbers
var i = 0
var j = 0
for var tempFloat1 in targetArr {
tempFloat1 = targetArr[i]
for tempFloat2 in targetArr{
if (tempFloat2 > tempFloat1) && (j > i) {
tempFloat1 = targetArr[j]
targetArr.swapAt(i, j)
}
j += 1
}
i += 1
j = 0
}
return targetArr
}
我是磊怀 QQ 2849765859