【问题标题】:Swift Dictionary lookup causing compile-time errorSwift Dictionary 查找导致编译时错误
【发布时间】:2014-10-10 14:44:24
【问题描述】:

我正在尝试使用 Swift,但遇到了一个让我有些困惑的问题。给定一个整数索引,我试图获取 Dictionary 的相应键并返回与之关联的值。

以如下结构为例:

Class CustomClass {
    private var collection: [String: [SifterIssue]] = ["MyStringKey": [MyCustomCollectionClass]()]

    /* ... */
}

我尝试这样解决问题:

var keys = Array(self.collection.keys)
var key: String = keys[section] as String
return self.collection[key].count // error is flagged here

但发现这会导致编译器错误,指出 'String' 不能转换为 'DictionaryIndex'。难住了,我尝试了一个稍微冗长的解决方案,并惊讶地发现它编译并没有问题。

var keys = Array(self.collection.keys)
var key: String = keys[section] as String
var collection: [MyCustomCollectionClass] = self.collection[key]! as [MyCustomCollectionClass]
return issues.count

谁能向我解释为什么第一个解决方案拒绝编译?

【问题讨论】:

  • self.collection[key] 是可选的[SifterIssue]?,请尝试在[key] 之后使用?!

标签: arrays dictionary collections swift


【解决方案1】:

忽略致命的潜在错误是一个非常糟糕的主意。 Optionals 的全部原因是为了防止在运行时崩溃。

func collectionCount(#section: Int) -> Int? {
    var keys = Array(self.collection.keys)
    if section < keys.count {
    var key = keys[section] as String
        println("key: \(key)")
        return self.collection[key]!.count
    }
    else {
        // handle error here
        return nil
    }
}

输入“!”在不知道值可能 never 为 nil 的情况下展开包装比 Objective-C 对 nil 的处理要糟糕得多。如果这成为大量开发人员处理 Optional 的标准方式,那么 Swift 将是一场灾难。请不要这样做。

【讨论】:

  • 你说得对,盲目地展开而不测试 nil 是一个错误。为简洁起见,我这样做了,但删除了我的答案,因为您的答案结构很好,希望将来能帮助其他人。谢谢!
  • 不会使用超出keys 数组范围的section 调用keys[section] 也是致命错误吗?
  • 是的,已修复。有没有比对索引进行显式测试更好的方法?
  • @Zaph 我暂时想不出任何东西。但是,键数组有一个内置的惰性属性:self.collection.keys.array。所以,在边界检查section 之后,你可以这样做:let key = collection.keys.array[section]return collection[key]!.count。我认为不需要 keys[section] != nil,因为只要 section 在数组边界内,keys[section] 将始终返回有效的密钥。
  • @MikeS 我不知道键的惰性属性。有帮助!
【解决方案2】:

正如@Zaph 所说,忽略潜在的致命错误是一个坏主意,而 swift 的部分目的是帮助解决这个问题。这是我能想到的最“迅速”的代码:

func collectionCount(#section: Int) -> Int? {
    switch section {
    case 0..<collection.count: // Make sure section is within the bounds of collection's keys array
        let key = collection.keys.array[section] // Grab the key from the collection's keys array
        return collection[key]!.count // We can force unwrap collection[key] here because we know that key exists in collection
    default:
        return nil
    }
}

它使用 swift 的switch 语句的范围/模式匹配特性来确保sectioncollectionkeys 数组的边界内;这感觉比使用 if 更“迅速”,主要是因为我找不到在 if 语句中使用 swift 的 Range 的方法。它还使用collection.keys惰性属性array作为快捷方式,而不是使用Array(collection.keys)创建新的Array。由于我们已经确定sectioncollection.keys的范围内,所以当我们得到count时,我们可以强制解开collection[key]!

为了好玩,我还做了一个通用函数,它以集合作为输入来概括事物:

func collectionCount<T,U>(#collection: [T:[U]], #section: Int) -> Int? {
    switch section {
    case 0..<collection.count: // Make sure section is within the bounds of collection's keys array
        let key = collection.keys.array[section] // Grab the key from the collection's keys array
        return collection[key]!.count // We can force unwrap collection[key] here because we know that key exists in collection
    default:
        return nil
    }
}

[T:[U]] 基本上说collection 需要是Dictionary,其键为T,其值为ArrayU

【讨论】:

  • 我必须为@Mike S 提供一个独特而简洁的解决方案。更“迅速?”,可能基于下一个开发人员在遇到这种情况时会做的头疼的事情。 :-) 考虑到 Optionals 对开发人员的负面影响,我觉得 Swift 开发人员欠我们更好的语言结构来处理它们。对我来说,一门好的语言是一种不碍事的语言,一种我花更多时间思考我的代码而不是语言限制的语言。 Swift,IMO,不满足这一点。
猜你喜欢
  • 2017-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多