Swift, как сортировать массив настраиваемых объектов по значению свойства

скажем, у нас есть собственный class с именем imageFile, и этот class содержит два свойства.

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

многие из них хранятся в массиве

 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) 

вопрос: как я могу сортировать массив изображений по ‘fileID’ ASC или DESC?

Во-первых, объявите свой массив как типизированный массив, чтобы вы могли вызывать методы при повторе:

 var images : [imageFile] = [] 

Тогда вы можете просто сделать:

Swift 2

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

Swift 3 и 4

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

Пример выше дает порядок сортировки desc

[ Обновлено для Swift 3 с сортировкой (по 🙂 ] Это, используя трейлинг-закрытие:

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

где вы используете < или > зависимости от ASC или DESC, соответственно. Если вы хотите изменить массив images , используйте следующее:

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

Если вы собираетесь делать это повторно и предпочитаете определять функцию, один из способов:

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

а затем использовать как:

 images.sort(by: sorterForFileIDASC) 

Почти каждый дает, как напрямую, позвольте мне показать эволюцию:

вы можете использовать методы экземпляра массива:

 // 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 }) 

Подробное объяснение принципа работы сортировки см. В разделе «Сортированная функция» .

Swift 3

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

В Swift 3.0

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

Две альтернативы

1) Заказ исходного массива с sortInPlace

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

2) Использование альтернативного массива для хранения упорядоченного массива

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

Вы также можете сделать что-то вроде

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

поэтому ваш массив изображений будет сохранен как отсортированный

С Swift 4, Array имеет два метода, называемых sorted() и sorted(by:) . Первый метод, sorted() , имеет следующее объявление:

Возвращает элементы коллекции, отсортированные.

 func sorted() -> [Element] 

Второй метод, sorted(by:) , имеет следующее объявление:

Возвращает элементы коллекции, отсортированные с использованием заданного предиката в качестве сравнения между элементами.

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

1. Сортировать по возрастанию для сопоставимых объектов

Если тип элемента внутри вашей коллекции соответствует протоколу Comparable , вы сможете использовать sorted() , чтобы отсортировать элементы с возрастающим порядком. Следующий код игровой площадки показывает, как использовать 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. Сортировка по убыванию для сопоставимых объектов

Если тип элемента внутри вашей коллекции соответствует протоколу Comparable , вам придется использовать sorted(by:) для сортировки элементов с убывающим порядком.

 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. Сортировка по возрастанию или убыванию для несопоставимых объектов

Если тип элемента внутри вашей коллекции НЕ соответствует протоколу Comparable , вам придется использовать sorted(by:) , чтобы отсортировать элементы с восходящим или нисходящим порядком.

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

Обратите внимание, что Swift также предоставляет два метода под названием sort() и sort(by:) виде копий sorted() и sorted(by:) если вам нужно сортировать свою коллекцию на месте.

Swift с 2 по 4

Первоначальный ответ искал сортировку массива пользовательских объектов с использованием некоторого свойства. Ниже я покажу вам несколько удобных способов сделать такое же поведение с быстрыми структурами данных!

Маленькие вещи вышли из пути, я немного изменил ImageFile. Имея это в виду, я создаю массив с тремя файлами изображений. Обратите внимание, что метаданные являются необязательным значением, проходящим в нуле, поскольку ожидается такой параметр.

  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 имеет свойство с именем size. В следующих примерах я покажу вам, как использовать операции сортировки w / properties, такие как размер.

наименьший по размеру (<)

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

самый большой и самый маленький (>)

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

Затем мы будем сортировать, используя имя свойства String. Аналогичным образом используйте сортировку для сравнения строк. Но обратите внимание, что внутренний блок возвращает результат сравнения. Этот результат определит сортировку.

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 } 

Следующий мой любимый способ сортировки, во многих случаях у вас будут дополнительные свойства. Теперь не волнуйтесь, мы собираемся сортироваться так же, как и выше, за исключением того, что мы должны обрабатывать ноль! В производстве;

Я использовал этот код, чтобы заставить все экземпляры в моем массиве с последними значениями свойств nil. Затем закажите метаданные, используя предполагаемые развернутые значения.

  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 } 

Возможно иметь вторичный сорт для опциональных. Например; можно показать изображения с метаданными и упорядочить по размеру.

Если вы собираетесь сортировать этот массив в нескольких местах, может возникнуть смысл сделать тип массива 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. Во-первых, я создал изменяемый массив типа imageFile (), как показано ниже

 var arr = [imageFile]() 

Создайте изменяемое изображение объекта типа imageFile () и присвойте значение свойствам, как показано ниже

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

Теперь добавьте этот объект в массив arr

  arr.append(image) 

Теперь назначьте разные свойства одному и тому же изменяемому объекту, т. Е. Изображение

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

Теперь снова добавим объект изображения в массив arr

  arr.append(image) 

Теперь мы будем применять Ascending order по свойству fileId в массиве arr объектов. Использовать <символ для возрастания

  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 

Теперь мы применим Descending order на свойство fileId в объектах array arr. Использовать > символ в порядке убывания

  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 

В Swift 4.1. Для использования отсортированного заказа

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

Если вы не используете пользовательские объекты, а вместо них вместо типов значений реализуете протокол Comparable (Int, String и т. Д.), Вы можете просто сделать это:

 myArray.sort(>) //sort descending order 

Пример:

 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 

Если вы хотите отсортировать исходный массив пользовательских объектов. Вот еще один способ сделать это в Swift 2.1

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

Где id - целое число. Вы можете использовать тот же оператор < operator для свойств String .

Вы можете узнать больше о его использовании, взглянув на пример здесь: Swift2: Ближайшие клиенты

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

Печатает: "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"

Я делаю это так и работает:

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

  • Почему сопоставитель строк по умолчанию не поддерживает переходную последовательность?
  • Выполнение qsort vs std :: sort?
  • Сортировка строк в таблице данных
  • DataGridView с использованием SortableBindingList
  • Для чего нужен пузырь?
  • Сортировка строк, содержащих номер в Java
  • Как сортировать элементы TreeView с помощью SortDescriptions в Xaml?
  • Таблица сортировки неверна при нажатии кнопки сортировки более одного раза?
  • Оптимальный алгоритм для возврата значений верхнего k из массива длины N
  • Сортировка массива int в порядке убывания
  • Как реализовать автоматическую сортировку DataGridView?
  • Давайте будем гением компьютера.