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

290

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

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?

Теги:
arrays
sorting

13 ответов

532
Лучший ответ

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

var images : [imageFile] = []

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

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

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

  • 1
    Мне не хватало части объявления массива, она сделала трюк Array <imageFile>.
  • 0
    Использование декларации не повлияло на мой тест ...
Показать ещё 10 комментариев
153

[Обновлено для 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)
  • 0
    как я могу подать в суд на это со строкой? мне нужно отсортировать строку по длине
  • 0
    @MuneefM просто возвращает string1.length <string2.length
Показать ещё 2 комментария
43

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

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

// general form of closure
images.sortInPlace({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })

// types of closure 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 argument list along with "in" keyword can be omitted, $0, $1, $2, and so on are used to refer the closure 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 })

Подробное объяснение принципа работы сортировки см. Отсортированная функция.

32

Swift 3

people = people.sorted(by: { $0.email > $1.email })
  • 0
    Я попробовал это с датой сравнения, не мог заставить его работать. Любая идея?
  • 0
    В каком формате были даты? Строка, NSDate?
Показать ещё 6 комментариев
19

В Swift 3.0

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

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

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)
  • 3
    ре 2) Какой смысл создавать пустой массив и отбрасывать его в следующей строке? Я бы рекомендовал использовать var assignmentsO : [Assignment] или объединить его в одну строку, используя let assignmentsO = self.assignments.sort({ $0.order < $1.order })
  • 2
    Привет, Герман! Существует очень тонкая грань между написанием читаемого и эффективного кода. В этом случае единственный момент - сделать его более читабельным для сообщества;) наслаждайтесь!
15

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

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

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

11

С 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:), если вам нужно отсортировать коллекцию на месте.

  • 2
    Это отличный ответ! Спасибо вам большое!
6

Если вы собираетесь сортировать этот массив в нескольких местах, может возникнуть смысл сделать тип массива 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]"
5

Если вы не используете пользовательские объекты, а вместо этого вместо типов значений реализуете протокол 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
  • 0
    в swift 3 это myArray.sorted(by: >)
2

Swift 4.0

   var arr = [imageFile]()

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

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

   arr = arr.sorted(by: {$0.fileId < $1.fileId}) // < for Ascending order, use > for descending order 
   print("sorted array is",arr[0].fileId)// sorted array is 13
   print("sorted array is",arr[1].fileId)//sorted array is 14
2

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

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

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

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

1

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню