【发布时间】:2017-08-27 01:27:13
【问题描述】:
目前我让用户导入从Excel 或Numbers 创建的CSV-file。工作表有多个字段,我可以毫无问题地导入这些字段。
但是,其中一个字段如下所示:
"[Title1: (100: S11), (100: S12), (100: 10), (100: 2), (100: 3)], [Title2: (300: 50), (300: 90), (300: 100a), (300: D), (300: E)], [Title3: (500: 2), (500: 112), (500: 6), (500: 110), (500: 113)]"
我应该如何将此字段分成如下所示的字典:
//[String: [[Int: String]]]
[
"Title1": [[100: "S11"], [100: "S12"], [100: "10"], [100: "2"], [100: "3"]],
"Title2": [[300: "50"], [300: "90"], [300: "100a"], [300: "D"], [300: "E"]],
"Title3": [[500: "2"], [500: "112"], [500: "6"], [500: "110"], [500: "113"]]
]
这个字段是由用户自己创建的,这似乎有点太复杂了,容易出错。也许更好的问题是如何更好地格式化而不是将该字段拆分到我想要的字典中?
也许是简化版:
//[String: [Int: [String]]]
[
"Title1": [100: ["S11", "S12", "10", "2", "3"]],
"Title2": [300: ["50", "90", "100a", "D", "E"]],
"Title3": [500: ["2", "112", "6", "110", "113"]]
]
关于这个字段的一些解释:
标题:可以是任何东西,它是嵌套字典的标题
嵌套字典中的key可以是100, 200, 300, 400, 500 or 600
嵌套字典中的值是String,与它们在嵌套字典中的键一起构成唯一键。
这意味着:
100: "S11" and 200: "S11" // valid
100: "S11" and 100: "S11" // not valid
extension String {
// Separate alphanumeric characters
func split(_ number: Int = 1) -> [String] {
let number = max(number, 1)
return self.components(separatedBy: CharacterSet.alphanumerics.inverted).filter { $0.characters.count > number - 1 }
}
}
let string = "Appetizer: (100: S11), (100: S12), (100: 10), (100: 2), (100: 3) * Main: (300: 50), (300: 90), (300: 100a), (300: D), (300: E) * Dessert: (500: 2), (500: 112), (500: 6), (500: 110), (500: 113)"
let values = string.components(separatedBy: "*").map { $0.split() }
var result: [String: [Int: [String]]] = [:]
values.forEach {
guard let key = $0.first else { return }
result[key] = result[key] ?? [:]
let values = $0.dropFirst()
let name = values.enumerated().filter { $0.0 % 2 == 0 }.map { $0.1 }
let code = values.enumerated().filter { $0.0 % 2 != 0 }.map { $0.1 }
zip(name, code).forEach {
guard let category = Int($0.0) else { return }
result[key]?[category] = (result[key]?[category] ?? []) + [$0.1]
}
}
这段代码产生了我想要的结果,但它看起来很丑陋,而且过于依赖值的位置(而不是检查值)。
关于如何使用更简单、更优雅的方式来做到这一点有什么建议吗?
【问题讨论】:
-
您应该定义一个结构来保存这些数据。使用数组和字典会很快变得混乱。
(100: S11), (100: S12)代表什么? -
我将创建一个结构(或者更确切地说是
NSManagedObject,因为我必须将其保存在 CoreData 中)。(100: S12)代表(Int: String),其中100代表类别,S12代表标识符。 -
我认为您应该认真重新考虑您的 Excel 模板。导出为纯文本已经够糟糕的了。嵌套更糟糕。如果类别名称中有空格,您的解决方案将不起作用,例如“今日特卖”
-
@CodeDifferent:这就是我害怕的原因。我让用户使用 Excel 导入的唯一原因是因为我至少需要一种让他们将菜单导入应用程序的方法。其他字段仅包含 1 个“字符串”,因此应该没问题(尽管我需要检查它们是否真正“唯一”。但是,此问题中的字段是创建一个“完整菜单”,其中包含可供选择的选项。在正常情况下他们不需要指定这个,但他们可以。另外我真的希望它保存在 1 个
CSV文件中,这样我也可以使用相同的格式导出。 -
话虽如此,考虑到这些限制,我还能使用什么建议?另外我正在考虑使用
NSRegularExpression来实现结果,所以我可以将标题放在括号中,将项目放在括号中。
标签: swift string csv dictionary