【问题标题】:Function remove(atOffsets:) complains about wrong type only at runtime函数 remove(atOffsets:) 仅在运行时抱怨错误类型
【发布时间】:2021-12-22 03:01:16
【问题描述】:

我在 Playground 中有这个非常简单的代码。它编译时没有错误,但是当我尝试运行它时,remove(atOffsets:) 函数出现错误。这是为什么呢?

enum CandyColor: CaseIterable {
    case red, green, yellow, brown
}
enum CandyFilling: CaseIterable {
    case chocolade, nuts
}

extension CaseIterable {
    static var random: Self {
        Self.allCases.randomElement()!
    }
}

typealias Candy = (color: CandyColor, filling: CandyFilling)

var candies = (0...20).map{ _ in Candy(color: CandyColor.random, filling: CandyFilling.random)}

var redWithChocolade = [Candy]()
var yellowWithNuts = [Candy]()
var brownAndGreenWithChocolade = [Candy]()

var indiciesToRemove = IndexSet()
for (index, candy) in candies.enumerated() {
    switch candy {
    case (.red, .chocolade):
        redWithChocolade.append(candy)
        indiciesToRemove.insert(index)
    case (.yellow, .nuts):
        yellowWithNuts.append(candy)
        indiciesToRemove.insert(index)
    case let(c) where [.brown, .green].contains(c.color) && c.filling == .chocolade:
        brownAndGreenWithChocolade.append(c)
        indiciesToRemove.insert(index)
    default:
        break
    }
}

candies.remove(atOffsets: indiciesToRemove) // Error: candidate expects value of type 'Int' for parameter #1

print("Left in heap: \(candies)") 

【问题讨论】:

  • 在 XCode 12.5 上运行良好,你有什么版本的 XCode?​​span>
  • 我正在使用 Xcode 13.0 (13A233),@iUrii。

标签: arrays swift


【解决方案1】:

你应该添加:

import SwiftUI

到您的脚本,因为它包含 remove(atOffsets:) 实现并且 XCode 不会隐式导入此框架。

【讨论】:

  • 不知何故它有所帮助,虽然我已经有 import UIKit 声明并且应该足够了。
【解决方案2】:

为什么不直接使用filter(_:)

let leftOver = candies.filter { candy in 
    switch candy {
    case (.red, .chocolade): 
        redWithChocolade.append(candy)
        return false
    case (.yellow, .nuts):
         yellowWithNuts.append(candy)
         return false
     case (.brown, .chocolade):
         fallthrough
     case (.green, .chocolade):
         brownORGreenWithChocolade.append(candy)
         return false
      default: return true
    }
}

或者如果你真的需要就地移除,removeAll(where:):

candies.removeAll { candy in 
    switch candy {
    case (.red, .chocolade): 
        redWithChocolade.append(candy)
        return true
    case (.yellow, .nuts):
         yellowWithNuts.append(candy)
         return true
     case (.brown, .chocolade):
         fallthrough
     case (.green, .chocolade):
         brownORGreenWithChocolade.append(candy)
         return true
      default: return false
    }
}

【讨论】:

  • 我认为一次删除多个索引是一种有效的方法。主要的问题是为什么明显的事情不起作用。但是你的建议看起来很有趣也很方便。
  • 我建议的函数式编程方法应该比两次遍历元素执行得更好:一次删除要删除的索引,另一次删除这些索引处的元素。采用filter(_:)removeAll(where:) 可以通过一次循环元素来完成所有操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
相关资源
最近更新 更多