Ordenar objetos en matriz por fecha

Tengo una matriz que contiene un objeto llamado HistoryObject y tiene propiedades como “fecha”, “nombre”, etc.

Estoy ordenando la matriz así:

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

que se supone que ordena la fecha de más nueva a más antigua. Por ejemplo:

  • 30 de junio de 2016
  • 29 de junio de 2016

etc.

Pero cuando mi matriz contiene “2 de julio de 2016”, la matriz ordenada se convierte en:

  • 30 de junio de 2016
  • 29 de junio de 2016
  • 2 de julio de 2016

Donde “2 de julio de 2016” debería estar en la parte superior después de la clasificación, ¿ahora está en la parte inferior? ¿Como puedo solucionar este problema?

Usando Swift 4 y Swift 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) 

Usando Swift 2

Por ejemplo, tiene la matriz con fechas y otra 1 matriz, donde guardará las fechas convertidas:

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

Después de eso convertimos las fechas:

 var dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd" for dat in testArray { var date = dateFormatter.dateFromString(dat) convertedArray.append(date!) } 

Y el resultado:

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

Para Swift 3

 var testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"] var convertedArray: [Date] = [] var dateFormatter = DateFormatter() dateFormatter.dateFormat = "dd/MM/yyyy" for dat in testArray { var date = dateFormatter.date(from: dat) convertedArray.append(date!) } //Approach : 1 convertedArray.sort(){$0 < $1} //Approach : 2 convertedArray.sorted(by: {$0.timeIntervalSince1970 < $1.timeIntervalSince1970}) print(convertedArray) 

Evitando la variable extra de convertArray

Usando Swift 4 y Swift 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) 

Usted tiene una matriz historyArray que contiene una matriz de HistoryObject . Cada HistoryObject contiene una cadena de fecha en el formato “MM dd, yyyy”

Desea ordenar sus objetos de historial por sus valores de fecha.

Para hacerlo de manera eficiente, primero necesita obtener valores de Date para todos los objetos. Una forma de hacerlo sería agregar una Var Date vacía a su objeto de historial que se calcula a partir de la cadena de fecha. Si no quieres hacer eso, puedes:

  1. Asigne su matriz de objetos históricos a una matriz de objetos Date usando un DateFormatter.
  2. Use la función zip() para combinar la matriz de objetos históricos y la matriz de objetos de fecha en una matriz de tuplas.
  3. Ordenar la matriz de tuplas.
  4. Asigne la matriz de tuplas a una matriz de objetos de historial.

El código para hacer eso podría verse más o menos así:

Versión 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) } 

Si agrega una lazy var date varita lazy var date a su HistoryObject, el código de clasificación es MUCHO más simple:

Versión 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) }