[英]Filter and sort swift array of dictionaries
我有以下数组:
let parent = [ ["Step":"S 3", "Desc":"Do third step" ],
["Step":"S 1", "Desc":"Do first step" ],
["Step":"S 2", "Desc":"Do second step" ],
["Step":"P 1", "Desc":"Some other thing" ] ]
如何以最少的步骤过滤和排序数组(使用过滤器和排序函数),以便获得以下输出字符串或标签——
1.做第一步
2.做第二步
3.做第三步
我建议过滤、排序、枚举、映射和加入:
let results = parent
.filter { $0["Step"]?.first == "S" }
.sorted { $0["Step"]!.compare($1["Step"]!, options: .numeric) == .orderedAscending }
.enumerated()
.map { (index, value) in "\(index + 1). \(value["Desc"]!)" }
.joined(separator: "\n")
一个关键的考虑因素是使用.numeric
比较,以便“S 10”出现在“S 9”之后,而不是“S 1”和“S 2”之间。 如果您在字符串中嵌入一个数值,您不想进行简单的字符串比较。
我还加入了该枚举,因为如果您删除一个项目,您可能希望确保列表中的数字不会仅仅因为Step
字符串中的特定编码而跳过某个值。
不相关的是,字典对于这样的事情来说是一个糟糕的模型。 我建议自定义类型:
struct Task {
enum TaskType {
case step
case process // or whatever "P" is supposed to stand for
}
let sequence: Int
let type: TaskType
let taskDescription: String
}
let parent = [Task(sequence: 3, type: .step, taskDescription: "Do third step"),
Task(sequence: 1, type: .step, taskDescription: "Do first step"),
Task(sequence: 2, type: .step, taskDescription: "Do second step"),
Task(sequence: 3, type: .process, taskDescription: "Some other thing")]
let results = parent
.filter { $0.type == .step }
.sorted { $0.sequence < $1.sequence }
.map { "\($0.sequence). \($0.taskDescription)" }
.joined(separator: "\n")
描述的答案:
首先,您需要过滤数组以仅获取步骤; 根据发布的parent
数组,有效步骤似乎应该包含一个键为“Step”和一个格式为“S#”的值,因此它可以被过滤为:
let filtered = parent.filter { (currentDict) -> Bool in
// get the value for key "Step"
guard let value = currentDict["Step"] else {
return false
}
// check ifthe value matches the "S #"
let trimmingBySpace = value.components(separatedBy: " ")
if trimmingBySpace.count != 2 || trimmingBySpace[0] != "S" || Int(trimmingBySpace[1]) == nil {
return false
}
return true
}
到目前为止会得到:
[["Step": "S 3", "Desc": "Do third step"],
["Step": "S 1", "Desc": "Do first step"],
["Step": "S 2", "Desc": "Do second step"]]
其次,您将按“Step”键的值对filtered
数组进行排序:
let sorted = filtered.sorted { $0["Step"]! < $1["Step"]! }
你应该得到:
[["Step": "S 1", "Desc": "Do first step"],
["Step": "S 2", "Desc": "Do second step"],
["Step": "S 3", "Desc": "Do third step"]]
最后,您将映射已sorted
数组以获取描述值:
let descriptions = sorted.map { $0["Desc"] ?? "" }
descriptions
应该是:
["Do first step", "Do second step", "Do third step"]
一步到位:
let result = parent.filter { (currentDict) -> Bool in
// get the value for key "Step"
guard let value = currentDict["Step"] else {
return false
}
// check ifthe value matches the "S #"
let trimmingBySpace = value.components(separatedBy: " ")
if trimmingBySpace.count != 2 || trimmingBySpace[0] != "S" || Int(trimmingBySpace[1]) == nil {
return false
}
return true
}.sorted {
$0["Step"]! < $1["Step"]!
}.map {
$0["Desc"] ?? ""
}
print(result) // ["Do first step", "Do second step", "Do third step"]
func sortStep(step1:[String:String], step2:[String:String]) -> Bool {
guard let s1 = step1["Desc"], let s2 = step2["Desc"] else {
return false
}
return s1 < s2
}
let orderedStep = parent.sorted { sortStep(step1:$0, step2:$1) }
print("\(orderedStep)")
我使用了强制展开假设您的结构将保持如上所述。 随意根据需要添加任何检查。
parent.filter { $0["Step"]!.contains("S") }.sorted { $0["Step"]! < $1["Step"]!
}.map { print($0["Desc"]!) }
let sorted = parent.filter({ ($0["Step"]?.hasPrefix("S"))! }).sorted { $0["Step"]! < $1["Step"]!}
var prefix = 0
let strings = sorted.reduce("") { (partial, next) -> String in
prefix += 1
return partial + "\(prefix)." + next["Desc"]! + "\n"
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.