我有一个字典数组,我的字典是[String:AnyObject]。以下是一些数据:
[{
name = Joe;
score = 50;
favorite = Phone;
startDate = "2015-10-15";
startingTime = "2015-10-15 19:00:00 +0000";
finished = "<null>";
}, {
name = Mark;
score = 60;
favorite = Phone;
startDate = "2015-10-16”;
startingTime = "2015-10-16 19:00:00 +0000";
finished = "<null>";
}, {
name = Joe;
score = 30;
favorite = Phone;
startDate = "2015-10-15";
startingTime = "2015-10-15 19:00:00 +0000";
finished = "<null>";
}]
我想要的是能够先按名称排序,然后按开始时间排序,然后如果两者都匹配则按分数排序(我将分数存储为字符串)。
我知道这是非常错误但是我输入了:
test.sort({ $0.name! < $1.name! })
这给了我一个错误“无法使用'((_,_) - &gt; _)'类型的参数列表调用'sort'。”
任何人都可以对如何做到这一点有所了解吗?
**已更新为具有答案的视图控制器中的代码
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var allArray = [AnyObject]()
var array = [String:AnyObject]()
array["name"] = "Joe"
array["score"] = 50 as Int
array["favorite"] = "Phone"
array["startDate"] = "2015-10-15"
let date = NSDate()
array["date"] = date
array["finished"] = nil
allArray.append(array)
array["name"] = "Mark"
array["score"] = 60 as Int
array["favorite"] = "Phone"
array["startDate"] = "2015-10-16"
array["date"] = date
array["finished"] = nil
allArray.append(array)
array["name"] = "Joe"
array["score"] = 30 as Int
array["favorite"] = "Phone"
array["startDate"] = "2015-10-15"
array["date"] = date
array["finished"] = nil
allArray.append(array)
println(allArray)
allArray.sort {
if let name0 = $0["name"] as? String, name1 = $1["name"] as? String
where name0 != name1 {
return name0 < name1
}
// You said 'startingTime' in your question your code showed 'date'
if let date0 = $0["date"] as? NSDate, date1 = $1["date"] as? NSDate
where date0.timeIntervalSince1970 != date1.timeIntervalSince1970 {
return date0.timeIntervalSince1970 < date1.timeIntervalSince1970
}
// You have 'score' as String. I think you would want a numeric type instead
return ($0["score"] as! Int) < ($1["score"] as! Int)
}
println(allArray)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
谢谢!
答案 0 :(得分:1)
如果编译器变得奇怪,请尝试使用闭包参数更明确。
这种排序方法似乎对我有用。
arr = arr.sort { a, b in
if a["name"] == b["name"] {
if a["startingTime"] == b["startingTime"] {
return a["score"] > b["score"]
}
return a["startingTime"] > b["startingTime"]
} else {
return a["name"] > b["name"]
}
}
答案 1 :(得分:0)
看起来这很有效,警卫就是这样,我不必在比较中处理打开(因为这样我爱护,使代码更清洁IMO)
let test : [[String:AnyObject]] = [["name":"joe", "time":1, "score":5], ["name":"joe", "time":1, "score":3], ["name":"joe", "time":1, "score":7]]
let sorted = test.sort{
guard let name = $0["name"] as? String,
let time = $0["time"] as? Int,
let score = $0["score"] as? Int,
let name1 = $1["name"] as? String,
let time1 = $1["time"] as? Int,
let score1 = $1["score"] as? Int else{
//unwrapping failed, sort is going to be bad
return false
}
if name == name1 {
if time == time1 {
return score < score1
}else {
return time < time1
}
}else {
return name < name1
}
}
print(sorted)
答案 2 :(得分:0)
以下是一些使给定代码更好的代码片段。首先将这些添加到文件的开头,以使日期可比。
public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs === rhs || lhs.compare(rhs) == .OrderedSame
}
public func <(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.compare(rhs) == .OrderedAscending
}
extension NSDate: Comparable { }
然后在你的方法中使用下面的语法(这是swift 2):
var allArray = [AnyObject]()
var array = [String:AnyObject]()
array["name"] = "Joe"
array["score"] = "50"
array["favorite"] = "Phone"
array["startDate"] = "2015-10-15"
let date = NSDate()
array["startingTime"] = date
array["finished"] = nil
allArray.append(array)
array["name"] = "Mark"
array["score"] = "60"
array["favorite"] = "Phone"
array["startDate"] = "2015-10-16"
array["startingTime"] = date
array["finished"] = nil
allArray.append(array)
array["name"] = "Joe"
array["score"] = "30"
array["favorite"] = "Phone"
array["startDate"] = "2015-10-15"
array["startingTime"] = date
array["finished"] = nil
allArray.append(array)
print(allArray)
allArray.sortInPlace { i,j in (i["name"] as! String) < (j["name"] as! String) || (i["startingTime"] as! NSDate) < (j["startingTime"] as! NSDate) }
我更喜欢你使用这样的语法。这是一种更快捷的方式来声明一系列字典。
let xyz = [
[
"name" : "Joe",
"score" : 50,
"favorite" : "Phone",
"startDate" : "2015-10-15",
"startingTime" : "2015-10-15 19:00:00 +0000",
"finished" : "<null>"
], [
"name" : "Mark",
"score" : 60,
"favorite" : "Phone",
"startDate" : "2015-10-16",
"startingTime" : "2015-10-16 19:00:00 +0000",
"finished" : "<null>"
], [
"name" : "Joe",
"score" : 30,
"favorite" : "Phone",
"startDate" : "2015-10-15",
"startingTime" : "2015-10-15 19:00:00 +0000",
"finished" : "<null>"
]
]
var test = xyz.sort { ($0["name"] as! String) < ($1["name"] as! String) }
答案 3 :(得分:0)
只是将我的解决方案添加到已经拥挤的答案中,因为现有的答案都不令我满意。
// allArray is as initiated in your viewDidLoad method
let sortedArray = allArray.sort {
if let name0 = $0["name"] as? String, name1 = $1["name"] as? String
where name0 != name1 {
return name0 < name1
}
// You said 'startingTime' in your question but your code showed 'date'
if let date0 = $0["date"] as? NSDate, date1 = $1["date"] as? NSDate
where date0.timeIntervalSince1970 != date1.timeIntervalSince1970 {
return date0.timeIntervalSince1970 < date1.timeIntervalSince1970
}
// You have 'score' as String. I think you would want a numeric type instead
return ($0["score"] as! Int) < ($1["score"] as! Int)
}
代码充满了强制转换,因为您使用AnyObject
作为值类型。