[英]Sort an Array of dictionaries with date key
我正在 swift 4 中開發一個 iOS 項目。我有一個類似字典的數組
var myArray = [[String: AnyObject]]()
字典包含姓名、年齡created_at(字符串中的日期)、國籍等。我需要按照日期字符串格式的“created_at”鍵的升序對myArray 進行排序。 我怎樣才能做到這一點? 請幫我。 我檢查了所有解決方案,但沒有得到排序數組。
我的陣列就像,
(
{
name: X
age: 26
created_at: "1991-10-10 18:29:05"
nationality: Indian
},
{
name: Y
age: 30
created_at: "2000-05-10 18:29:05"
nationality: Indian
},
)
你可以使用這個:
let sortedArray = (array as NSArray).sortedArray(using: [NSSortDescriptor(key: "created_at", ascending: true)]) as! [[String:AnyObject]]
用if let
把它包起來,這樣你就不會強制轉換。
但我建議您為這本詞典制作一個模型,特別是因為您將重復使用它與多個數據。
對對象數組進行排序更容易(類似於我在下面發布的內容):
編輯:按Date
而不是String
對日期進行排序。 下面的代碼假定您的createdAt
已轉換為 Date 對象。
array.sorted(by: { ($0.createdAt).compare($1.createdAt) == .orderedAscending })
我建議為這些創建一個模型,但當然你也可以這樣做
array.sort { (firstItem, secondItem) -> Bool in
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
if let dateAString = firstItem["created_at"] as? String,
let dateBString = secondItem["created_at"] as? String,
let dateA = dateFormatter.date(from: dateAString),
let dateB = dateFormatter.date(from: dateBString){
return dateA.compare(dateB) == .orderedAscending
}
return false
}
您可以使用NSSortDescriptor
let sortedArray = (myArray as NSArray).sortedArray(using: [NSSortDescriptor(key: "created_at", ascending: true)]) as! [[String:AnyObject]]
工作示例
let dateDICT = [["name" : "a", "date": "1991-10-10 18:29:05"],["name" : "b", "date": "2000-05-10 18:29:05"],["name" : "c", "date": "2000-05-10 18:29:04"]]
print(dateDICT)
排序前
[["name": "a", "date": "1991-10-10 18:29:05"], ["name": "b", "date": "2000-05-10 18:29:05"], ["name": "c", "date": "2000-05-10 18:29:04"]]
這里第三個元素日期小於第二個元素的一秒。
排序代碼
let sortedArray = (dateDICT as NSArray).sortedArray(using: [NSSortDescriptor(key: "date", ascending: true)]) as! [[String:AnyObject]]
print(sortedArray)
排序后的結果
[["name": a, "date": 1991-10-10 18:29:05], ["name": c, "date": 2000-05-10 18:29:04], ["name": b, "date": 2000-05-10 18:29:05]]
在您的情況下,鍵created_at: "1991-10-10 18:29:05"
是您的日期字符串,因此您必須將日期字符串轉換為Date
對象並使用Date().timeIntervalSince1970
方法獲取時間間隔。 它將返回一個Double
,您可以使用此Double
值比較您的日期。
為了更方便,請參考以下代碼片段。
//Model For your JSON
struct MyModel:Codable {
var age:Int?
var name:String?
var nationality:String?
var created_at:String?
}
//MY Array
var dataSource = [MyModel]()
//Helper method to convert the date string into timeInterval
func getMilisecFrom(dateString:String) -> Double{
let formator = DateFormatter()
formator.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let date = formator.date(from: dateString)
else {
return Date().timeIntervalSince1970
}
return date.timeIntervalSince1970
}
// method to short the array
func ShortByDate(){
let shortedData = dataSource.sorted(by: {(getMilisecFrom(dateString: $0.created_at ?? "")) > (getMilisecFrom(dateString: $1.created_at ?? ""))})
dataSource = shortedData
}
在您的情況下,要獲得正確的結果,您可以根據Date
相等邏輯而不是字符串進行排序。 為了做到這一點,您應該首先從字符串中獲取Date
,通過了解給定日期所需的格式(在您的情況下為yyyy-MM-dd HH:mm:ss
),從而根據該格式對其進行排序。 例子:
let myArray: [[String: AnyObject]] = [["name": "X" as AnyObject, "age": 26 as AnyObject, "created_at": "1991-10-10 18:29:05" as AnyObject],
["name": "Y" as AnyObject, "age": 30 as AnyObject, "created_at": "2000-05-10 18:29:05" as AnyObject]]
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let sorted = myArray.sorted { first, second -> Bool in
guard let firstCreatedAt = first["created_at"] as? String,
let firstCreatedAtDate = formatter.date(from: firstCreatedAt),
let secondCreatedAt = second["created_at"] as? String,
let secondCreatedAtDate = formatter.date(from: secondCreatedAt) else {
return false
}
return firstCreatedAtDate < secondCreatedAtDate
}
print(sorted)
// [["name": X, "age": 26, "created_at": 1991-10-10 18:29:05], ["created_at": 2000-05-10 18:29:05, "name": Y, "age": 30]]
由於Date
符合Comparable
協議,您可以使用>
或<
運算符簡單地比較兩個日期。
注意:日期字符串比較也將起作用。 所以你可以用return firstCreatedAtDate < secondCreatedAtDate
替換return firstCreatedAt < secondCreatedAt
。
你使用蘋果的排序功能。 我們只需要比較created_at
字段的值。 因為當我們比較字符串的時候是靠ASCII來比較的。
let result = myArray.sorted(by: { (object1, object2) in bool
guard let temp1 = object1["created_at"] as? String,
let temp2 = object2["created_at"] as? String else { return false }
return temp1 < temp2
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.