按日期排序数组中的对象

时间:2016-07-03 09:32:07

标签: arrays swift sorting

我有一个包含名为HistoryObject的对象的数组,它具有“date”,“name”等属性。

我正在对数组进行排序:

 let sortedArray = HistoryArray.sort({ $0.date.compare($1.date) == NSComparisonResult.OrderedDescending})

应该将日期从较新到最旧排序。例如:

  • 2016年6月30日
  • 2016年6月29日

等。

但是当我的数组包含“2016年7月2日”时,排序的数组变为:

  • 2016年6月30日
  • 2016年6月29日
  • 2016年7月2日

“2016年7月2日”排序后应该排在最前面,现在它位于底部?我该如何解决这个问题?

7 个答案:

答案 0 :(得分:69)

使用Swift 4&斯威夫特3

let testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"]
var convertedArray: [Date] = []

var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"

for dat in testArray {
    let date = dateFormatter.date(from: dat)
    if let date = date {
        convertedArray.append(date)
    }
}

var ready = convertedArray.sorted(by: { $0.compare($1) == .orderedDescending })

print(ready)

使用Swift 2

例如,您拥有包含日期​​的数组和另外1个数组,您将保存转换后的日期:

var testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"]
var convertedArray: [NSDate] = []

之后我们转换日期:

var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"

for dat in testArray {
    var date = dateFormatter.dateFromString(dat)
    convertedArray.append(date!)
}

结果:

var ready = convertedArray.sort({ $0.compare($1) == .OrderedDescending })

print(ready)

答案 1 :(得分:13)

适用于Swift 3

process = subprocess.Popen(cmd, shell=True,stdout=subprocess.PIPE)
for line in iter(process.stdout.readline, ''):
    print line

答案 2 :(得分:5)

避免使用convertedArray的额外变量

使用Swift 4&斯威夫特3

let testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"]

var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"

var ready = convertedArray.sorted(by: { dateFormatter.date(from:$0).compare(dateFormatter.date(from:$1)) == .orderedDescending })

print(ready)

答案 3 :(得分:1)

您有一个数组historyArray,其中包含HistoryObject的数组。每个HistoryObject包含一个日期字符串,格式为“ MM dd,yyyy”

编辑:

(您要按历史记录对象的日期值对它们进行排序。尝试按日期字符串对具有日期 strings 的对象进行排序是一个坏主意,因为您必须将日期字符串转换为每次比较都使用可可Date对象,因此最终要一遍又一遍地将日期转换为日期对象,在我做的基准测试中,这导致排序运行的速度比批量转换日期字符串时慢了1200倍到Date对象进行排序之前,如下所述。)

为了高效地执行此操作,您需要首先获取所有对象的Date值。一种方法是将Date惰性变量添加到HistoryObject中,该变量是根据日期字符串计算得出的。如果您不想这样做,可以:

  1. 使用以下命令将历史对象数组映射到Date对象数组 DateFormatter。
  2. 使用zip()函数将历史对象数组与 将日期对象数组转换为元组数组。
  3. 对元组数组进行排序。
  4. 将元组数组映射回历史对象数组。

执行该操作的代码可能如下所示:

版本1

var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM dd, yyyy"

//I don't know what your HistoryObject looks like, so I'll fake it.
struct HistoryObject: CustomStringConvertible {
    let dateString: String
    let value: Int

    var description: String {
        return "date: \(dateString), value: \(value)"
    }
}

//Create an array of date strings.
let testArray = ["Jun 25, 2016", "Jun 30, 2016", "Jun 28, 2016", "Jul 2, 2016"]

//Use the array of date strings to create an array of type [HistoryObject]
let historyArray: [HistoryObject] = testArray.map {
    let value = Int(arc4random_uniform(1000))
    return HistoryObject(dateString: $0, value: value)
}

print("\n-----> Before sorting <-----")
historyArray.forEach { print($0) }

//Create an array of the `Dates` for each HistoryObject
let historyDates: [Date] = historyArray.map { dateFormatter.date(from: $0.dateString)!
}

//Combine the array of `Dates` and the array of `HistoryObjects` into an array of tuples
let historyTuples = zip(historyArray, historyDates)

//Sort the array of tuples and then map back to an array of type [HistoryObject]
let sortedHistoryObjects = historyTuples.sorted { $0.1 > $1.1}
    .map {$0.0}

print("\n-----> After sorting <-----")
sortedHistoryObjects.forEach { print($0) }

如果将lazy var date添加到HistoryObject中,则排序代码会更简单:

版本2:

//I don't know what your HistoryObject looks like, so I'll fake it.
class HistoryObject: CustomStringConvertible {
    let dateString: String
    lazy var date: Date = { dateFormatter.date(from: self.dateString)! }()
    let value: Int

    var description: String {
        return "date: \(dateString), value: \(value)"
    }

    init(dateString: String, value: Int) {
        self.dateString = dateString
        self.value = value
    }
}

//Create an array of date strings.
let testArray = ["Jun 25, 2016", "Jun 30, 2016", "Jun 28, 2016", "Jul 2, 2016"]

//Use the array of date strings to create an array of type [HistoryObject]
let historyArray: [HistoryObject] = testArray.map {
    let value = Int(arc4random_uniform(1000))
    return HistoryObject(dateString: $0, value: value)
}

print("\n-----> Before sorting <-----")
historyArray.forEach { print($0) }

let sortedHistoryArray = historyArray.sorted { $0.date > $1.date }
print("\n-----> After sorting <-----")
sortedHistoryArray.forEach { print($0) }

答案 4 :(得分:1)

请试试这个,它对我有用

let sortArr = prescriptionList?.medicationList?.sorted(by:{
            ($0.medicationDate?.stringDateToInt(requireFormatter: "yyyy-MM-dd HH:mm:ss", needFormatter: "yyyy-MM-dd HH:mm:ss", dateStr: $0.medicationDate ?? ""))! > $1.medicationDate!.stringDateToInt(requireFormatter: "yyyy-MM-dd HH:mm:ss", needFormatter: "yyyy-MM-dd HH:mm:ss", dateStr: $1.medicationDate ?? "")
        } )

extension String {
    
    func stringDateToInt(requireFormatter: String, needFormatter: String, dateStr: String) -> Int {
        var dateInt: Int = 0
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "\(requireFormatter)"
        if let date = dateFormatter.date(from: dateStr) {
            dateFormatter.dateFormat = "\(needFormatter)"
            dateInt = date.millisecondsSince1970
        }
        return dateInt
    }
}

答案 5 :(得分:0)

您可能要使用“ .sort”而不是“ .sorted”:

convertedArray.sort { (($0)?.compare($1))! == .orderedDescending }

答案 6 :(得分:0)

雨燕5

  1. 假设我们有一个对象数组,其日期为字符串:
struct Test {
    let dateStr: String
}
let testObjects = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "12 Jul, 2016"]
    .map(Test.init(dateStr:))
  1. 创建一个DateFormatter
var dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.dateFormat = "dd MMM, yyyy"
  1. map将每个项目复制到一个元组(测试,日期),然后按日期sort整个数组,然后再次map到测试对象:
let convertedObjects = testObjects
    .map { return ($0, dateFormatter.date(from: $0.dateStr)!) }
    .sorted { $0.1 > $1.1 }
    .map(\.0)

以类似的方式,我们可以将日期数组排序为字符串:

  1. 假设我们有一个数组:
let testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "12 Jul, 2016"]
  1. 创建一个DateFormatter
var dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.dateFormat = "dd MMM, yyyy"
  1. map将每个项目保留为Date,然后sort整个数组:
let convertedArray = testArray
    .compactMap(dateFormatter.date(from:))
    .sorted(by: >)