【问题标题】:"For-in loop requires '[String]?' to conform to 'Sequence'; did you mean to unwrap optional?" but I don't think I am using optionals“for-in 循环需要 '[String]?'符合'Sequence';你的意思是解开可选的吗?”但我不认为我在使用选项
【发布时间】:2021-05-27 07:05:08
【问题描述】:

这是我正在尝试做的,但简化了:

var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []

var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false } //I make an arr from a dictionary's keys of type [String:[String]]

for (key, val) in newdic{
     for arr in adictionary[key]{
          if !(adictionary[arr].contains(key)){
               newdic[key] = true
          }
     }
}

当我运行上面试图在 ios 应用程序中运行的代码的简化版本时,出现这些错误:

main.swift:12:28: 错误:可选类型 '[String]?' 的值必须解包为“[String]”类型的值 for arr in dictionary[key]{

main.swift:12:28:注意:使用 '??' 合并当可选值包含“nil”时提供默认值 for arr in dictionary[key]{

main.swift:12:28: 注意:使用 '!' 强制解包如果可选值包含“nil”,则中止执行 for arr in dictionary[key]{

我不明白,我在做什么有什么问题?这些错误是什么意思?似乎 Swift 认为我在某个地方有一个可选的?但我不知道我是怎么做的......非常感谢任何帮助。

如果我改变这一行:for arr in dictionary[key]{

To: for arr in dictionary[key]!{

它修复了问题,新的错误出现在 if !(a... 行。我仍然不明白为什么会修复它。

【问题讨论】:

  • adictionary[key] 始终是可选的。这就是字典的工作原理。
  • 正如马特所说,你“知道有一个与 key 关联的值,因为你首先从字典的键中获得了 key,但 Swift 并不“知道” . 访问字典总是返回一个可选的, 因为可能有也可能没有与给定键关联的值. 强制展开使问题消失, 但 nil 与?? [] 合并是一种更安全的方法. 你没有说你的代码实际上是试图实现的,但是Set 可能是一个更好的数据结构使用。Ben 如果你不需要预加载false;你的字典可以包含true/@ 987654329@

标签: ios swift for-in-loop


【解决方案1】:

Swift 字典访问总是返回 可选 值,因为如果键不存在,查找将返回 nil。由你来处理这个结果 optional 是一种安全的方式。添加! 很少是修复它的正确方法,因为如果返回nil,您的代码将崩溃。

你第一次得到一个可选就在这里:

for arr in adictionary[key] {

同样,Swift 不知道key 是否存在于adictionary 中,因此它返回一个可选。解决此问题的一种安全方法是使用字典查找,该查找在密钥不存在时返回 default 值。在这种情况下,返回一个空数组似乎是一个不错的选择,因为您的 for 循环将什么也不做:

for arr in adictionary[key, default:[]] {

接下来,您会在此处获得一个可选

if !(adictionary[arr].contains(key)){

同样,您需要决定如何安全地处理dictionary[arr] 可以返回nil 的事实。同样的技巧在这里起作用:如果arr 不存在,则返回一个空数组:

if !(adictionary[arr, default:[]].contains(key)){

这是您的代码的最终版本:

var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []

var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false } //I make an arr from a dictionary's keys of type [String:[String]]
print(newdic)

for key in newdic.keys {
    for arr in adictionary[key, default:[]] {
        if !(adictionary[arr, default:[]].contains(key)){
               newdic[key] = true
          }
     }
}

【讨论】:

  • 对不起,我不明白这部分:“在这种情况下,返回一个空数组似乎是一个不错的选择,因为你的 for 循环“为什么我要返回 [] 并退出我的函数?如果该键确实不作为另一个字典的键存在,我想我宁愿它只是跳过它并继续,所以 continue 语句会更有意义。我将在 swift 中查找 default 的作用,然后再回来讨论。还要查找 nil 合并是什么,我也不明白
  • default: 提供当键不存在时字典查找返回的值。对于我的代码,将返回一个空数组,它完全符合您的要求。由于数组中没有元素,因此将跳过内部 for 循环,代码将继续执行下一个键。
  • “if !(adictionary[arr, default:[]].contains(key)){“所以这基本上就像使用 nil 合并运算符?有点像说“?? []”,我理解对了吗?谢谢你教我
  • 是的,它非常类似于 nil 合并运算符 if !((adictionary[arr] ?? []).contains(key))) {,但它还有一个额外的好处,您可以将其附加到它上面。如果你创建了一个新字典来计算单词中的字母,你可以说dict[letter, default: 0] += 1,当你第一次看到一个字母时,它会创建字典条目并增加它。
【解决方案2】:

这是一个类似的方法,没有你提到的问题。

var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []

var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false }

let notEmptValues = adictionary.values.filter { $0.count > 0 }.reduce([], +)
let duplicates = Array(Set(notEmptValues.filter { i in notEmptValues.filter { $0 == i }.count > 1 })).sorted(by: { $0 < $1 })
if let result = adictionary.first(where: { $0.value.sorted(by: { $0 < $1 }) == duplicates })?.key {
    newdic[result] = true
}

print(newdic)

【讨论】:

    猜你喜欢
    • 2021-04-07
    • 2021-01-31
    • 2023-01-08
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    相关资源
    最近更新 更多