代码之家  ›  专栏  ›  技术社区  ›  maxMas

Swift 5:为什么会出现索引超出范围错误?

  •  0
  • maxMas  · 技术社区  · 2 年前

    我有两个数组,我将包括在一个带有对象实例的数组中。当我尝试这样做时,我得到一个错误,索引超出范围。

    我的代码如下。我不明白为什么会出现这个错误。有人能告诉我我做错了什么吗?

    import UIKit
    
    let mealName = ["Breakfast", "Lunch", "Dinner", "Breakfast", "Lunch", "Dinner", "Breakfast", "Lunch", "Dinner", "Snack", "Supper", "Snack", "Breakfast", "Snack", "Lunch", "Dinner", "Supper", "Snack", "Breakfast", "Snack", "Dinner", "Snack", "Snack", "Snack", "Breakfast", "Snack", "Lunch", "Snack", "Snack", "Snack", "Breakfast", "Snack", "Lunch", "Snack", "Snack", "Snack", "Snack"]
    
    let mealCalories = [725.03, 539.44, 849.49, 956.53, 267.18, 567.17, 353.47, 387.12, 700.76, 62.87, 857.35, 176.56, 123.79, 16.74, 813.74, 858.23, 127.26, 448.19, 932.62, 60.22, 880.55, 58.85, 78.48, 21.5, 564.74, 190.75, 911.01, 67.47, 81.44, 25.35, 954.94, 45.75, 858.71, 61.7, 189.75, 72.54, 75.84]
    
    
    struct Meal {
        var mealName: String
        var mealCalories: Double
    }
    
    var meals = [Meal]()
    
    for i in 0..<37 {
        meals[i].mealName = mealName[i]
        meals[i].mealCalories = mealCalories[i]
    }
    

    enter image description here

    1 回复  |  直到 2 年前
        1
  •  2
  •   Asteroid    2 年前

    var meals: [Meal] = [Meal](repeating: Meal(mealName: "", mealCalories: 0.0), count: 37)
    
    

    然后您可以参考膳食[i](0<=i<37)。

    如果要从空数组开始,可以向其中添加元素:

    var meals = [Meal]()
    

    然后:

    for i in 0..<37 {
        let meal = Meal(mealName: mealName[i], mealCalories: mealCalories[i])
        meals.append(meal)
    }
    

    在这种情况下,食物的长度会随着我的成长而增加。

        2
  •  0
  •   Alexander    2 年前

    你已经有一个 Meal 这就引出了一个问题:为什么不直接定义你的饮食?

    struct Meal {
        // Don't prefix the properties with "meal".
        // It leads to pointless code like "someMeal.mealName".
        // You already know it's a meal by the type.
        let name: String
        let calories: Double
    }
    
    let meals = [
        let meals = [
        Meal(name: "Breakfast", calories: 725.03),
        Meal(name: "Lunch",     calories: 539.44),
        Meal(name: "Dinner",    calories: 849.49),
        Meal(name: "Breakfast", calories: 956.53),
        Meal(name: "Lunch",     calories: 267.18),
        Meal(name: "Dinner",    calories: 567.17),
        Meal(name: "Breakfast", calories: 353.47),
        Meal(name: "Lunch",     calories: 387.12),
        Meal(name: "Dinner",    calories: 700.76),
        Meal(name: "Snack",     calories:  62.87),
        Meal(name: "Supper",    calories: 857.35),
        Meal(name: "Snack",     calories: 176.56),
        Meal(name: "Breakfast", calories: 123.79),
        Meal(name: "Snack",     calories:  16.74),
        Meal(name: "Lunch",     calories: 813.74),
        Meal(name: "Dinner",    calories: 858.23),
        Meal(name: "Supper",    calories: 127.26),
        Meal(name: "Snack",     calories: 448.19),
        Meal(name: "Breakfast", calories: 932.62),
        Meal(name: "Snack",     calories:  60.22),
        Meal(name: "Dinner",    calories: 880.55),
        Meal(name: "Snack",     calories:  58.85),
        Meal(name: "Snack",     calories:  78.48),
        Meal(name: "Snack",     calories:  21.50),
        Meal(name: "Breakfast", calories: 564.74),
        Meal(name: "Snack",     calories: 190.75),
        Meal(name: "Lunch",     calories: 911.01),
        Meal(name: "Snack",     calories:  67.47),
        Meal(name: "Snack",     calories:  81.44),
        Meal(name: "Snack",     calories:  25.35),
        Meal(name: "Breakfast", calories: 954.94),
        Meal(name: "Snack",     calories:  45.75),
        Meal(name: "Lunch",     calories: 858.71),
        Meal(name: "Snack",     calories:  61.70),
        Meal(name: "Snack",     calories: 189.75),
        Meal(name: "Snack",     calories:  72.54),
        Meal(name: "Snack",     calories:  75.84),
    ]
    

    如果并行阵列必须保留

    (例如,它们来自您无法控制的API)

    1. 一个数组已经存储了它自己的计数,而在其他地方计数的硬编码引入了分裂的真值源。这里的风险是它们不同步:

      • 如果添加了新的餐名/卡路里,但您忘记更新 37
      • 如果删除了一些餐名/卡路里,那么您的 将过大并导致越界错误。
    2. 您将索引到一个空数组中,而不是追加

    幸运的是,这些问题很容易解决!

    1. 将索引修复到末尾,并使用 append 相反:

      var meals = [Meal]()
      for i in 0..<37 {
          meals.append(Meal(name: mealNames[i], calories: mealCalories[i])
      }
      
    2. assert(mealNames.count == mealCalories.count,
          "Config error! The names and calories should match up one for one!")
      
      var meals = [Meal]()
      
      for i in 0..<meanNames.count {
          meals.append(Meal(name: mealNames[i], calories: mealCalories[i])
      }
      
    3. assert(mealNames.count == mealCalories.count, ...)
      
      var meals = [Meal]()
      
      for i in mealNames.indices {
          meals.append(Meal(name: mealNames[i], calories: mealCalories[i])
      }
      
    4. 完全忘记索引!只需使用 zip(_:_:) :

      assert(mealNames.count == mealCalories.count, ...)
      
      var meals = [Meal]()
      
      for (name, calories) in zip(mealNames, mealCalories) {
          meals.append(Meal(name: name, calories: calories))
      }
      
    5. 迭代输入、转换输入并生成新数组只是一个映射操作。

      assert(mealNames.count == mealCalories.count, ...)
      
      let meals = zip(mealNames, mealCalories).map { name, calories in
          Meal(name: name, calories: calories))
      }
      

      meals 不是通过重复突变构建的,我们现在可以使其成为 let 常数