我有一个递归枚举,其中大多数情况下具有相同类型的关联值:
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))
}
...使用一些默认案例来处理所有类似案例?
尽管我同意保罗的担心,即以Location
这种方式嵌套很奇怪,但基本问题是可以解决的。就我个人而言,我不会用a来解决它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(", ")
}
}
这里的教训是,枚举的第一个孩子是其所有数据的元组。
但是使用Mirror
起来更加脆弱(注意,我打开了崩溃的可能性)。尽管这里的枚举可能是一个很好的工具,但您仍然可能需要重新考虑这个数据结构。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句