Swift como ordenar matriz de objects personalizados por valor de propriedade

digamos que temos uma class personalizada chamada imageFile e essa class contém duas propriedades.

class imageFile { var fileName = String() var fileID = Int() } 

muitos deles armazenados em 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) 

pergunta é: como posso classificar matriz de imagens por ‘fileID’ ASC ou DESC?

Primeiro, declare sua matriz como uma matriz tipificada para poder chamar methods ao iterar:

 var images : [imageFile] = [] 

Então você pode simplesmente fazer:

Swift 2

 images.sorted({ $0.fileID > $1.fileID }) 

Swift 3 e 4

 images.sorted(by: { $0.fileID > $1.fileID }) 

O exemplo acima dá ordem de sorting desc

[ Atualizado para Swift 3 com sorting (por 🙂 ] Isso, explorando um encerramento final:

 images.sorted { $0.fileID < $1.fileID } 

onde você usa < ou > dependendo do ASC ou do DESC, respectivamente. Se você quiser modificar o array de images , use o seguinte:

 images.sort { $0.fileID < $1.fileID } 

Se você for fazer isso repetidamente e preferir definir uma function, uma delas é:

 func sorterForFileIDASC(this:imageFile, that:imageFile) -> Bool { return this.fileID > that.fileID } 

e então use como:

 images.sort(by: sorterForFileIDASC) 

Quase todo mundo dá como diretamente, deixe-me mostrar a evolução:

você pode usar os methods de instância do 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 uma explicação mais elaborada sobre o princípio de funcionamento da sorting, consulte The Sorted Function .

Swift 3

 people = people.sorted(by: { $0.email > $1.email }) 

No Swift 3.0

 images.sort(by: { (first: imageFile, second: imageFile) -> Bool in first. fileID < second. fileID }) 

Duas alternativas

1) Solicitando o array original com o sortInPlace

 self.assignments.sortInPlace({ $0.order < $1.order }) self.printAssignments(assignments) 

2) Usando uma matriz alternativa para armazenar o array ordenado

 var assignmentsO = [Assignment] () assignmentsO = self.assignments.sort({ $0.order < $1.order }) self.printAssignments(assignmentsO) 

Você também pode fazer algo como

 images = sorted(images) {$0.fileID > $1.fileID} 

então o seu array de imagens será armazenado como ordenado

Com o Swift 4, o Array possui dois methods chamados sorted() e sorted(by:) . O primeiro método, sorted() , tem a seguinte declaração:

Retorna os elementos da coleção, classificados.

 func sorted() -> [Element] 

O segundo método, sorted(by:) , tem a seguinte declaração:

Retorna os elementos da coleção, classificados usando o predicado fornecido como a comparação entre os elementos.

 func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element] 

1. Classifique com ordem crescente para objects comparáveis

Se o tipo de elemento dentro de sua coleção estiver em conformidade com o protocolo Comparable , você poderá usar sorted() para classificar seus elementos com ordem crescente. O seguinte código Playground mostra como 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. Classifique com ordem decrescente para objects comparáveis

Se o tipo de elemento dentro de sua coleção estiver de acordo com o protocolo Comparable , você terá que usar sorted(by:) para classificar seus elementos com uma ordem decrescente.

 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. Classifique com ordem crescente ou decrescente para objects não comparáveis

Se o tipo de elemento dentro de sua coleção NÃO estiver em conformidade com o protocolo Comparable , você terá que usar sorted(by:) para classificar seus elementos com ordem crescente ou decrescente.

 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] */ 

Observe que o Swift também fornece dois methods chamados sort() e sort(by:) como contrapartes de sorted() e sorted(by:) se você precisar classificar sua coleção no local.

Swift 2 a 4

A resposta original procurava classificar uma matriz de objects personalizados usando alguma propriedade. Abaixo, mostrarei algumas maneiras práticas de fazer o mesmo comportamento com estruturas de dados rápidas!

Pequenas coisas fora do caminho, eu mudei ImageFile sempre ligeiramente. Com isso em mente, eu crio um array com três arquivos de imagem. Observe que os metadados são um valor opcional, passando em nil como um parâmetro é esperado.

  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 tem uma propriedade chamada size. Para os exemplos a seguir, mostrarei como usar operações de sorting com propriedades como tamanho.

do menor ao maior tamanho (< )

  let sizeSmallestSorted = images.sorted { (initial, next) -> Bool in return initial.size < next.size } 

maior para menor (>)

  let sizeBiggestSorted = images.sorted { (initial, next) -> Bool in return initial.size > next.size } 

Em seguida, classificaremos usando o nome da propriedade String. Da mesma maneira, use a sorting para comparar cadeias de caracteres. Mas observe que o bloco interno retorna um resultado de comparação. Este resultado irá definir a sorting.

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 } 

Em seguida é a minha maneira favorita de classificar, em muitos casos, um terá propriedades opcionais. Agora não se preocupe, nós vamos classificar da mesma maneira como acima, exceto que temos que lidar com nada! Em produção;

Eu usei este código para forçar todas as instâncias em minha matriz com valores de propriedade nulo para ser o último. Em seguida, ordene os metadados usando os valores assumidos não desembrulhados.

  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 } 

É possível ter uma sorting secundária para opcionais. Por exemplo; pode-se mostrar imagens com metadados e ordenadas por tamanho.

Se você estiver classificando essa matriz em mais de um local, pode fazer sentido tornar seu tipo de matriz Comparável.

 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. Primeiro, criei uma matriz mutável do tipo imageFile () como mostrado abaixo

 var arr = [imageFile]() 

Crie uma imagem de object mutável do tipo imageFile () e atribua valor às propriedades conforme mostrado abaixo

  var image = imageFile() image.fileId = 14 image.fileName = "A" 

Agora, acrescente esse object ao array arr

  arr.append(image) 

Agora, atribua as propriedades diferentes ao mesmo object mutável, isto é, imagem

  image = imageFile() image.fileId = 13 image.fileName = "B" 

Agora, acrescente novamente o object de imagem ao array arr

  arr.append(image) 

Agora, aplicaremos a ordem crescente na propriedade fileId em objects array arr. Use para ordem crescente

  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 

Agora, aplicaremos a ordem decrescente na propriedade fileId em objects array arr. Use > símbolo para ordem 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 

Em Swift 4.1. Para uso de ordem classificada

 let sortedArr = arr.sorted { (id1, id2) -> Bool in return id1.fileId < id2.fileId // Use > for Descending order } 

Se você não estiver usando objects personalizados, mas sim tipos de valor que implementam o protocolo Comparable (Int, String, etc.), basta fazer isso:

 myArray.sort(>) //sort descending order 

Um exemplo:

 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 

Se você quiser classificar a matriz original de objects personalizados. Aqui está outra maneira de fazer isso no Swift 2.1

 var myCustomerArray = [Customer]() myCustomerArray.sortInPlace {(customer1:Customer, customer2:Customer) -> Bool in customer1.id < customer2.id } 

Onde id é um inteiro. Você também pode usar o mesmo operador < para propriedades String .

Você pode aprender mais sobre seu uso, observando um exemplo aqui: Swift2: Clientes próximos

 var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"] students.sort(by: >) print(students) 

Estampas: "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"

Eu faço assim e funciona:

var images = [imageFile]() images.sorted(by: {$0.fileID.compare($1.fileID) == .orderedAscending })