【问题标题】:Randomize an array随机化一个数组
【发布时间】:2016-11-01 19:23:30
【问题描述】:

我需要为我正在尝试快速构建的应用程序随机化一个数组,并测试我创建的函数,我将它放入带有示例数组的游乐场。我意识到这里有人问过这个问题:How do I shuffle an array in Swift? 但我只是想知道为什么这种特定方式不起作用。这是我的代码:

import UIKit

var arrayOne : [String] = ["????", "????", "????", "????", "????"]

func randomizeArray(array : [String]) -> [String] {
    var randomizedArray : [String] = []
    var copyOfArray : [String] = array
    repeat {
        let arrayCount : Int = array.count - 1
        let randomElement : Int = Int(arc4random_uniform(UInt32(arrayCount)))
        let arraySlice : String = array[randomElement]
        randomizedArray.append(arraySlice)
        copyOfArray.remove(at : randomElement)
    } while array.count > 0
    return randomizedArray
}

print(randomizeArray(array : arrayOne))

当我尝试使用数组 1 打印函数时,它显示“致命错误:索引超出范围。”任何想法为什么会发生这种情况?

【问题讨论】:

  • 对于包含 5 个元素的数组,您可以轻松地调试问题。在 Xcode 中单步执行代码,您会很快发现问题出在哪里。
  • 然后去掉所有不必要的类型注解...

标签: arrays swift swift3


【解决方案1】:

看起来有一些问题。

首先,最好远离重复循环。这种范式通常比简单的 while 循环更令人困惑。

其次,您的随机化器遗漏了数组的最后一项。

第三,你以一种不可预知的方式结合了数组和 copyOfArray 的使用

试试这个:

var arrayOne : [String] = ["?", "?", "?", "?", "?"]

func randomizeArray(array : [String]) -> [String] {
    var randomizedArray : [String] = []
    var copyOfArray : [String] = array
    while !copyOfArray.isEmpty {
        let arrayCount : Int = copyOfArray.count
        let randomElement : Int = Int(arc4random_uniform(UInt32(arrayCount)))
        let arraySlice : String = copyOfArray[randomElement]
        randomizedArray.append(arraySlice)
        copyOfArray.remove(at : randomElement)
    }
    return randomizedArray
}



print(randomizeArray(array : arrayOne))

【讨论】:

  • 那行得通。这样做可能比 for in 方式要慢,因为它必须不断计算随机数,但它更容易理解,所以从像我这样的初学者的角度来看,它可能会更好。
  • 它会更慢,因为它正在创建一个新数组而不是交换原始数组中的项目。
【解决方案2】:

当我尝试使用数组一打印函数时,它显示“致命 错误:索引超出范围。” 知道为什么会这样吗?

我会回答这个问题。

属性arrayCount(即array.count)在循环中是固定的:在您的示例中,固定为4。这意味着循环永远不会终止(array.count > 0 总是true)。此外,由于您将此数字用作随机数生成的上限,因此您很可能会得到3 的值。让我们在接下来的简短分析中假设randomElement 始终具有3 的值(并注意randomIndex 将是一个更合适的名称)。

copyOfArray的初始大小为5,最多允许索引访问copyOfArray[4]。经过两次迭代,copyOfArray 的大小为3(由于删除了copyOfArray.remove(at: randomElement) 处的元素),这意味着此时copyOfArray[3] 将尝试访问越界的索引。在另一个迭代中,即使copyOfArray[2] 也超出了范围。由于循环永远不会终止,它迟早会因索引越界运行时异常而崩溃,因为copyOfArray 越来越小(朝向空数组,[]),同时copyOfArray.remove(at: randomElement) 不断尝试删除范围0...3

声明

mutating func remove(at index: Int) -> Element

参数

index

要移除的元素的位置。 index 必须是有效的 数组的索引

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    • 2017-08-31
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    相关资源
    最近更新 更多