arrays - ordenamiento - ordenar un array de objetos javascript
Swift cómo ordenar la matriz de objetos personalizados por valor de propiedad (15)
Casi todos dan como directamente, déjame mostrarte la evolución:
Puedes usar los métodos de instancia de Array:
// general form of closure
images.sortInPlace({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
// types of closure''s parameters and return value can be inferred by Swift, so they are omitted along with the return arrow (->)
images.sortInPlace({ image1, image2 in return image1.fileID > image2.fileID })
// Single-expression closures can implicitly return the result of their single expression by omitting the "return" keyword
images.sortInPlace({ image1, image2 in image1.fileID > image2.fileID })
// closure''s argument list along with "in" keyword can be omitted, $0, $1, $2, and so on are used to refer the closure''s first, second, third arguments and so on
images.sortInPlace({ $0.fileID > $1.fileID })
// the simplification of the closure is the same
images = images.sort({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
images = images.sort({ image1, image2 in return image1.fileID > image2.fileID })
images = images.sort({ image1, image2 in image1.fileID > image2.fileID })
images = images.sort({ $0.fileID > $1.fileID })
Para una explicación detallada sobre el principio de funcionamiento del género, vea La función ordenada .
digamos que tenemos una clase personalizada llamada imageFile y esta clase contiene dos propiedades.
class imageFile {
var fileName = String()
var fileID = Int()
}
muchos de ellos almacenados en Array
var images : Array = []
var aImage = imageFile()
aImage.fileName = "image1.png"
aImage.fileID = 101
images.append(aImage)
aImage = imageFile()
aImage.fileName = "image1.png"
aImage.fileID = 202
images.append(aImage)
la pregunta es: ¿cómo puedo ordenar la matriz de imágenes por ''fileID'' ASC o DESC?
Con Swift 4, Array
tiene dos métodos llamados sorted()
y sorted(by:)
. El primer método, sorted()
, tiene la siguiente declaración:
Devuelve los elementos de la colección, ordenados.
func sorted() -> [Element]
El segundo método, sorted(by:)
, tiene la siguiente declaración:
Devuelve los elementos de la colección, ordenados usando el predicado dado como la comparación entre los elementos.
func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element]
1. Ordenar con orden ascendente para objetos comparables.
Si el tipo de elemento dentro de su colección cumple con el protocolo Comparable
, podrá usar sorted()
para ordenar sus elementos en orden ascendente. El siguiente código de Patio de juegos muestra cómo usar sorted()
:
class ImageFile: CustomStringConvertible, Comparable {
let fileName: String
let fileID: Int
var description: String { return "ImageFile with ID: /(fileID)" }
init(fileName: String, fileID: Int) {
self.fileName = fileName
self.fileID = fileID
}
static func ==(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID == rhs.fileID
}
static func <(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID < rhs.fileID
}
}
let images = [
ImageFile(fileName: "Car", fileID: 300),
ImageFile(fileName: "Boat", fileID: 100),
ImageFile(fileName: "Plane", fileID: 200)
]
let sortedImages = images.sorted()
print(sortedImages)
/*
prints: [ImageFile with ID: 100, ImageFile with ID: 200, ImageFile with ID: 300]
*/
2. Ordenar con orden descendente para objetos comparables
Si el tipo de elemento dentro de su colección cumple con el protocolo Comparable
, tendrá que usar sorted(by:)
para ordenar sus elementos en orden descendente.
class ImageFile: CustomStringConvertible, Comparable {
let fileName: String
let fileID: Int
var description: String { return "ImageFile with ID: /(fileID)" }
init(fileName: String, fileID: Int) {
self.fileName = fileName
self.fileID = fileID
}
static func ==(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID == rhs.fileID
}
static func <(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID < rhs.fileID
}
}
let images = [
ImageFile(fileName: "Car", fileID: 300),
ImageFile(fileName: "Boat", fileID: 100),
ImageFile(fileName: "Plane", fileID: 200)
]
let sortedImages = images.sorted(by: { (img0: ImageFile, img1: ImageFile) -> Bool in
return img0 > img1
})
//let sortedImages = images.sorted(by: >) // also works
//let sortedImages = images.sorted { $0 > $1 } // also works
print(sortedImages)
/*
prints: [ImageFile with ID: 300, ImageFile with ID: 200, ImageFile with ID: 100]
*/
3. Ordenar con orden ascendente o descendente para objetos no comparables
Si el tipo de elemento dentro de su colección NO se ajusta al protocolo Comparable
, tendrá que usar sorted(by:)
para ordenar sus elementos en orden ascendente o descendente.
class ImageFile: CustomStringConvertible {
let fileName: String
let fileID: Int
var description: String { return "ImageFile with ID: /(fileID)" }
init(fileName: String, fileID: Int) {
self.fileName = fileName
self.fileID = fileID
}
}
let images = [
ImageFile(fileName: "Car", fileID: 300),
ImageFile(fileName: "Boat", fileID: 100),
ImageFile(fileName: "Plane", fileID: 200)
]
let sortedImages = images.sorted(by: { (img0: ImageFile, img1: ImageFile) -> Bool in
return img0.fileID < img1.fileID
})
//let sortedImages = images.sorted { $0.fileID < $1.fileID } // also works
print(sortedImages)
/*
prints: [ImageFile with ID: 300, ImageFile with ID: 200, ImageFile with ID: 100]
*/
Tenga en cuenta que Swift también proporciona dos métodos llamados sort()
y sort(by:)
como contrapartes de sorted()
y sorted(by:)
si necesita ordenar su colección en el lugar.
Lo hago así y funciona.
var images = [imageFile]() images.sorted(by: {$0.fileID.compare($1.fileID) == .orderedAscending })
Primero, declare su Array como una matriz escrita para que pueda llamar a los métodos cuando itere:
var images : [imageFile] = []
Entonces simplemente puedes hacer:
Swift 2
images.sorted({ $0.fileID > $1.fileID })
Swift 3 y 4
images.sorted(by: { $0.fileID > $1.fileID })
El ejemplo de arriba da el orden de desc
Si desea ordenar la matriz original de objetos personalizados. Aquí hay otra manera de hacerlo en Swift 2.1
var myCustomerArray = [Customer]()
myCustomerArray.sortInPlace {(customer1:Customer, customer2:Customer) -> Bool in
customer1.id < customer2.id
}
Donde id
es un entero. También puede utilizar el mismo operador <
para las propiedades de String
.
Puede aprender más sobre su uso mirando un ejemplo aquí: Swift2: Clientes cercanos
Si no está utilizando objetos personalizados, sino tipos de valores que implementan el protocolo Comparable (Int, String, etc.), simplemente puede hacer esto:
myArray.sort(>) //sort descending order
Un ejemplo:
struct MyStruct: Comparable {
var name = "Untitled"
}
func <(lhs: MyStruct, rhs: MyStruct) -> Bool {
return lhs.name < rhs.name
}
// Implementation of == required by Equatable
func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
return lhs.name == rhs.name
}
let value1 = MyStruct()
var value2 = MyStruct()
value2.name = "A New Name"
var anArray:[MyStruct] = []
anArray.append(value1)
anArray.append(value2)
anArray.sort(>) // This will sort the array in descending order
Si va a ordenar esta matriz en más de un lugar, puede tener sentido hacer que su tipo de matriz sea comparable.
class MyImageType: Comparable, Printable {
var fileID: Int
// For Printable
var description: String {
get {
return "ID: /(fileID)"
}
}
init(fileID: Int) {
self.fileID = fileID
}
}
// For Comparable
func <(left: MyImageType, right: MyImageType) -> Bool {
return left.fileID < right.fileID
}
// For Comparable
func ==(left: MyImageType, right: MyImageType) -> Bool {
return left.fileID == right.fileID
}
let one = MyImageType(fileID: 1)
let two = MyImageType(fileID: 2)
let twoA = MyImageType(fileID: 2)
let three = MyImageType(fileID: 3)
let a1 = [one, three, two]
// return a sorted array
println(sorted(a1)) // "[ID: 1, ID: 2, ID: 3]"
var a2 = [two, one, twoA, three]
// sort the array ''in place''
sort(&a2)
println(a2) // "[ID: 1, ID: 2, ID: 2, ID: 3]"
Swift 4.0 y 4.1. Primero, creé una matriz mutable de tipo imageFile () como se muestra a continuación
var arr = [imageFile]()
Cree una imagen de objeto mutable de tipo imageFile () y asigne un valor a las propiedades como se muestra a continuación
var image = imageFile()
image.fileId = 14
image.fileName = "A"
Ahora, agregue este objeto a la matriz arr
arr.append(image)
Ahora, asigne las diferentes propiedades al mismo objeto mutable, es decir, la imagen
image = imageFile()
image.fileId = 13
image.fileName = "B"
Ahora, nuevamente agregue el objeto de imagen a la matriz arr
arr.append(image)
Ahora, aplicaremos la orden Ascendente en la propiedad fileId en los objetos de matriz arr. Use <símbolo para orden ascendente
arr = arr.sorted(by: {$0.fileId < $1.fileId}) // arr has all objects in Ascending order
print("sorted array is",arr[0].fileId)// sorted array is 13
print("sorted array is",arr[1].fileId)//sorted array is 14
Ahora, aplicaremos el orden Descendente en la propiedad fileId en los objetos de matriz ar . Utilizar > símbolo para orden descendente
arr = arr.sorted(by: {$0.fileId > $1.fileId}) // arr has all objects in Descending order
print("Unsorted array is",arr[0].fileId)// Unsorted array is 14
print("Unsorted array is",arr[1].fileId)// Unsorted array is 13
En Swift 4.1. Para uso ordenado ordenado
let sortedArr = arr.sorted { (id1, id2) -> Bool in
return id1.fileId < id2.fileId // Use > for Descending order
}
También puedes hacer algo como
images = sorted(images) {$0.fileID > $1.fileID}
por lo que su matriz de imágenes se almacenará según lo ordenado
[ Actualizado para Swift 3 with sort (by :) ] This, explotando un cierre final:
images.sorted { $0.fileID < $1.fileID }
donde usas <
o >
dependiendo de ASC o DESC, respectivamente. Si desea modificar la matriz de images
, use lo siguiente:
images.sort { $0.fileID < $1.fileID }
Si va a hacer esto repetidamente y prefiere definir una función, una forma es:
func sorterForFileIDASC(this:imageFile, that:imageFile) -> Bool {
return this.fileID > that.fileID
}
y luego usar como
images.sort(by: sorterForFileIDASC)
Dos alternativas
1) Ordenar la matriz original con sortInPlace
self.assignments.sortInPlace({ $0.order < $1.order })
self.printAssignments(assignments)
2) Usando una matriz alternativa para almacenar la matriz ordenada
var assignmentsO = [Assignment] ()
assignmentsO = self.assignments.sort({ $0.order < $1.order })
self.printAssignments(assignmentsO)
En Swift 3.0
images.sort(by: { (first: imageFile, second: imageFile) -> Bool in
first. fileID < second. fileID
})
Swift 2 a 4
La respuesta original buscaba ordenar una matriz de objetos personalizados usando alguna propiedad. A continuación, te mostraré algunas formas prácticas de realizar este mismo comportamiento con estructuras de datos rápidas.
Pequeñas cosas fuera del camino, cambié ImageFile muy ligeramente. Con eso en mente, creo una matriz con tres archivos de imagen. Tenga en cuenta que los metadatos son un valor opcional y se pasa un valor nulo como parámetro.
struct ImageFile {
var name: String
var metadata: String?
var size: Int
}
var images: [ImageFile] = [ImageFile(name: "HelloWorld", metadata: nil, size: 256), ImageFile(name: "Traveling Salesmen", metadata: "uh this is huge", size: 1024), ImageFile(name: "Slack", metadata: "what''s in this stuff?", size: 2048) ]
ImageFile tiene una propiedad llamada tamaño. Para los siguientes ejemplos, le mostraré cómo usar las operaciones de clasificación con propiedades como el tamaño.
de menor a mayor tamaño (<)
let sizeSmallestSorted = images.sorted { (initial, next) -> Bool in
return initial.size < next.size
}
de mayor a menor (>)
let sizeBiggestSorted = images.sorted { (initial, next) -> Bool in
return initial.size > next.size
}
A continuación vamos a ordenar usando el nombre de la propiedad String. De la misma manera, use ordenar para comparar cadenas. Pero note que el bloque interno devuelve un resultado de comparación. Este resultado definirá la clasificación.
AZ (.orderedAscending)
let nameAscendingSorted = images.sorted { (initial, next) -> Bool in
return initial.name.compare(next.name) == .orderedAscending
}
ZA (.orderedDescending)
let nameDescendingSorted = images.sorted { (initial, next) -> Bool in
return initial.name.compare(next.name) == .orderedDescending
}
La siguiente es mi forma favorita de ordenar, en muchos casos uno tendrá propiedades opcionales. Ahora no se preocupe, vamos a clasificar de la misma manera que antes, ¡pero tenemos que manejar nada! En producción;
Utilicé este código para forzar que todas las instancias de mi matriz con valores de propiedad nula sean las últimas. Luego ordene los metadatos usando los valores supuestos no envueltos.
let metadataFirst = images.sorted { (initial, next) -> Bool in
guard initial.metadata != nil else { return true }
guard next.metadata != nil else { return true }
return initial.metadata!.compare(next.metadata!) == .orderedAscending
}
Es posible tener una clasificación secundaria para opcionales. Por ejemplo; Uno podría mostrar imágenes con metadatos y ordenadas por tamaño.
Swift 3
people = people.sorted(by: { $0.email > $1.email })
var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
students.sort(by: >)
print(students)
Impresiones: "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"