swift 选择排序—初学者使用swift语言遇到的坑

    xiaoxiao2022-07-14  142

    刚刚开始学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

    最新回复(0)