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

21 篇文章 0 订阅

刚刚开始学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循环会自动遍历数组中的每个元素。无需使用数组下标获取元素,
如上我定义了 tempFloat1tempFloat2 便利的值,但是在执行了之后却不是我想的那样的结果。
在这里插入图片描述
数组还是原来的数组,没有发生变化

我尝试打了无数个断点,推演了无数次,总觉得这个方法没有问题呀,两个变量的值也在发生变化。可是结果就是不变,这可头大了
于是乎,我猜想,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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值