Swift如何按属性值对自定义对象数组进行排序

时间:2014-06-09 22:27:01

标签: arrays sorting swift

假设我们有一个名为imageFile的自定义类,该类包含两个属性。

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

许多存储在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)

问题是:如何通过' fileID'对图像阵列进行排序? ASC还是DESC?

18 个答案:

答案 0 :(得分:799)

首先,将Array声明为类型化数组,以便在迭代时调用方法:

var images : [imageFile] = []

然后你就可以做到:

Swift 2

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

Swift 3&斯威夫特4& Swift 5

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

上面的示例提供了 desc 排序顺序

答案 1 :(得分:198)

[针对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)

答案 2 :(得分:50)

几乎每个人都直接给出如何,让我展示一下演变:

您可以使用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 })

有关排序工作原理的详细说明,请参阅The Sorted Function

答案 3 :(得分:41)

Swift 3

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

答案 4 :(得分:27)

使用Swift 5,Array有两种名为sorted()sorted(by:)的方法。第一种方法sorted()具有以下声明:

  

返回集合的元素,已排序。

func sorted() -> [Element]

第二种方法sorted(by:)具有以下声明:

  

返回集合的元素,使用给定的谓词作为元素之间的比较进行排序。

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

#1。按可比较对象的升序排序

如果集合中的元素类型符合Comparable协议,您将能够使用sorted()以按升序对元素进行排序。以下Playground代码显示了如何使用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:)的对应方。

答案 5 :(得分:23)

在Swift 3.0中

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

答案 6 :(得分: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)

答案 7 :(得分:16)

您也可以执行类似

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

因此您的图像数组将存储为已排序

答案 8 :(得分:15)

Swift 2到4

原始答案试图使用某些属性对自定义对象数组进行排序。下面我将向您展示一些方便的方法来执行与快速数据结构相同的行为!

小事情发生了,我稍微改变了ImageFile。考虑到这一点,我创建了一个包含三个图像文件的数组。请注意,元数据是一个可选值,传递为nil作为参数是预期的。

 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的属性。对于以下示例,我将向您展示如何使用具有大小等属性的排序操作。

从最小到最大的尺寸(&lt;)

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

从最大到最小(&gt;)

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

接下来,我们将使用String属性名称进行排序。以相同的方式,使用sort来比较字符串。但请注意内部块返回比较结果。这个结果将定义排序。

A-Z(.orderedAscending)

    let nameAscendingSorted = images.sorted { (initial, next) -> Bool in
      return initial.name.compare(next.name) == .orderedAscending
    }

Z-A(.orderedDescending)

    let nameDescendingSorted = images.sorted { (initial, next) -> Bool in
      return initial.name.compare(next.name) == .orderedDescending
    }

接下来是我最喜欢的排序方式,在很多情况下,会有一个可选的属性。现在不用担心,我们将按照与上面相同的方式进行排序,除非我们必须处理nil!在生产中;

我使用此代码强制数组中所有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
    }

可以对选项进行二次排序。例如;一个人可以用元数据显示图像并按大小排序。

答案 9 :(得分:14)

Swift 4.0,4.1&amp; 4.2首先,我创建了类型为imageFile()的可变数组,如下所示

SELECT *
FROM
(
  SELECT COUNT(*)
  FROM AA_V_ATS_Richieste R
  WHERE R.IdTipoRichiesta = 1 
  AND   R.DataInizio >= @DATA_INIZIO
  AND   R.DataFine   <= @DATA_FINE
) subquery(ttl)
WHERE @DATA_INIZIO IS NOT NULL;

创建imageFile()类型的可变对象图像,并为属性赋值,如下所示

var arr = [imageFile]()

现在,将此对象追加到数组arr

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

现在,将不同的属性分配给同一个可变对象,即图像

    arr.append(image)

现在,再次将图像对象追加到数组arr

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

现在,我们将在数组arr对象的 fileId 属性中应用升序。使用&lt;升序

的符号
    arr.append(image)

现在,我们将在数组arr对象的 fileId 属性上应用降序。使用&gt;降序的符号

 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

在Swift 4.1中。 &安培; 4.2对于已排序的订单使用

 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

答案 10 :(得分:6)

如果您打算在多个位置对此数组进行排序,那么使您的数组类型可比较可能是有意义的。

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]"

答案 11 :(得分: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

答案 12 :(得分:3)

我这样做是有效的:

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

答案 13 :(得分:2)

如果要对原始自定义对象数组进行排序。这是在Swift 2.1中另一种方法

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

id是整数。您也可以对<属性使用相同的String运算符。

通过查看示例,您可以了解有关其使用的更多信息: Swift2: Nearby Customers

答案 14 :(得分:2)

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]

students.sort(by: >)

print(students)

打印:"["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"

答案 15 :(得分:1)

您可以通过以下方式从fileID属性返回排序后的数组:

快捷键2

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

快速3或4

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

Swift 5.0

let sortedArray = images.sorted {
    $0.fileID < $1.fileID
}

答案 16 :(得分:0)

快速3&4&5

我遇到了与小写字母和大写字母有关的问题

所以我做了这段代码

let sortedImages = images.sorted(by: { $0.fileID.lowercased() < $1.fileID.lowercased() })

然后在那之后使用sortedImages

答案 17 :(得分:0)

使用KeyPath排序

您可以像这样按KeyPath进行排序:

myArray.sorted(by: \.fileName, <) /* using `<` for ascending sorting */

通过实施这个有用的扩展程序。

extension Collection{
    func sorted<Value: Comparable>(
        by keyPath: KeyPath<Element, Value>,
        _ comparator: (_ lhs: Value, _ rhs: Value) -> Bool) -> [Element] {
        sorted { comparator($0[keyPath: keyPath], $1[keyPath: keyPath]) }
    }
}

希望Swift在不久的将来将其添加到语言的核心。