gpt4 book ai didi

swift 2 : Is there any way to use 'default' in the switch statement of enum with associated values?

转载 作者:搜寻专家 更新时间:2023-10-31 19:34:29 25 4
gpt4 key购买 nike

我有一个递归枚举,其中大多数情况具有相同类型的关联值:

indirect enum Location {
case Title(String?)
case Region(Location)
case Area(Location, Location)
case City(Location, Location)
case Settlement(Location, Location)
case Street(Location, Location)
case House(Location, Location)
}

我想做的是形成一个漂亮的字符串描述,其中将包括所有非零标题。

func getStringFromLocation(location: Location) -> String? {
var parts: [String?] = []

switch location {
case .Title(let title): return title
case .House(let title, let parent):
parts.append(getStringFromLocation(parent))
parts.append(getStringFromLocation(title))
case .Street(let title, let parent):
parts.append(getStringFromLocation(parent))
parts.append(getStringFromLocation(title))
case .Settlement(let title, let parent):
parts.append(getStringFromLocation(parent))
parts.append(getStringFromLocation(title))
case .City(let title, let parent):
parts.append(getStringFromLocation(parent))
parts.append(getStringFromLocation(title))
case .Area(let title, let parent):
parts.append(getStringFromLocation(parent))
parts.append(getStringFromLocation(title))
case .Region(let title):
parts.append(getStringFromLocation(title))
}

return parts
.filter { $0 != nil }
.map { $0! }
.joinWithSeparator(", ")
}

问题是七种可能的情况中有五种完全相同,而且我有一堆复制粘贴的代码,我认为这不是很好。如果我有一百个案例的枚举怎么办?

有什么办法可以这样写吗?

switch location {
case .Title(let title):
parts.append(title)
case .Region(let title):
parts.append(getStringFromLocation(title))
default (let title, let parent):
parts.append(getStringFromLocation(parent))
parts.append(getStringFromLocation(title))
}

...使用一些默认情况来处理所有类似情况?

最佳答案

虽然我同意 Paul 的担忧,即以这种方式精确嵌套 Location 很奇怪,但基本问题是可以解决的。就个人而言,我不会用 default 来解决它,我只是简化代码并使用 Swift 给我们的工具(比如 CustomStringConvertible;我还在你的标签上贴上标签数据;只有两个具有完全不同含义的 Location 元素太困惑了):

indirect enum Location: CustomStringConvertible {
case Title(String?)
case Region(Location)
case Area(title: Location, parent: Location)
case City(title: Location, parent: Location)
case Settlement(title: Location, parent: Location)
case Street(title: Location, parent: Location)
case House(title: Location, parent: Location)

var description: String {

func format(locs: (Location, Location)) -> String {
return [locs.0, locs.1].map{$0.description}.filter{$0 != ""}.joinWithSeparator(", ")
}

switch self {
case .Title(let title): return title ?? ""

case .Region(let title): return "\(title)"

case .House(let data): return format(data)
case .Street(let data): return format(data)
case .Settlement(let data): return format(data)
case .City(let data): return format(data)
case .Area(let data): return format(data)
}
}
}

请注意我是如何将整个元组卸载到 data 中的。您不必在模式匹配中将元组分开。枚举永远不会有多个关联数据。他们总是只有一个:一个元组。 (函数也是如此。所有函数都接受一个值并返回一个值。该值可能恰好是一个元组。)

但是如果你真的想去掉那个重复的return format(data),那么你可以通过Mirror。 (你可以通过Mirror解决相当多的事情。在你做之前你应该非常小心。这种情况只是重复输入,而不是重复逻辑。一点点重复输入不是你应该创造的需要消除很多复杂性。)

这是你的做法:

var description: String {
switch self {
case .Title(let title): return title ?? ""

case .Region(let title): return "\(title)"

default:
let m = Mirror(reflecting: self)
guard let locs = (m.children.first?.value as? (Location, Location)) else {
preconditionFailure("Unexpected data in enum. Probably missing a case somewhere.")
}
return [locs.0, locs.1].map{$0.description}.filter{$0 != ""}.joinWithSeparator(", ")
}
}

这里的教训是,枚举的第一个 child 是其所有数据的元组。

但是使用Mirror 更加脆弱(注意我打开了崩溃的可能性)。虽然枚举在这里可能是一个很好的工具,但您可能仍需要重新考虑这种数据结构。

关于 swift 2 : Is there any way to use 'default' in the switch statement of enum with associated values?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33440039/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com