假设我们有一个名为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'升序或降序?


当前回答

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

students.sort(by: >)

print(students)

彼得Prints:“[””、“科菲Kweku”、“”、“Akosua Abena”、“]”

其他回答

如果您想对自定义对象的原始数组进行排序。在Swift 2.1中有另一种方法

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

其中id为整数。您也可以对String属性使用相同的<操作符。

你可以通过下面的例子了解更多关于它的用法: Swift2:附近的顾客

如果数组元素符合Comparable,那么你可以简单地使用函数语法:

array.sort(by: <)

如果你是基于自定义类型排序,你所需要做的就是实现<运算符:

class ImageFile {
    let fileName: String
    let fileID: Int
    let fileSize: Int
    static func < (left: ImageFile, right: ImageFile) -> Bool {
        return left.fileID < right.fileID
    }
}

但是,有时您不需要一种标准的比较imagefile的方法。也许在某些上下文中,您希望基于fileID对图像进行排序,而在其他地方,您希望基于fileSize对图像进行排序。对于动态比较,您有两个选项。

(by: sorted)

images = images.sorted(by: { a, b in
    // Return true if `a` belongs before `b` in the sorted array
    if a.fileID < b.fileID { return true }
    if a.fileID > b.fileID { return false }
    // Break ties by comparing file sizes
    return a.fileSize > b.fileSize
})

你可以使用尾随闭包来简化语法:

images.sorted { ... }

但是手动输入if语句会导致代码很长(如果我们想通过基于文件名排序来打破文件大小的束缚,我们将会有一个相当长的if厄运链)。我们可以通过使用全新的SortComparator协议(macOS 12+, iOS 15+)来避免这种语法:

排序(使用:)

files = files.sorted(using: [
    KeyPathComparator(\.fileID, order: .forward),
    KeyPathComparator(\.fileSize, order: .reverse),
])

这段代码根据文件ID()对文件进行排序。Forward表示升序),并根据文件大小(。反向意味着下降)。\。fileID语法是我们指定关键路径的方式。您可以根据需要扩展比较器列表。

你也可以这样做

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

你的图像数组会以排序的方式存储

在Swift 3.0中

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

Swift 2到4

最初的答案寻求使用某些属性对自定义对象数组进行排序。下面我将向您展示一些使用swift数据结构实现相同行为的简便方法!

我稍微改变了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的属性。对于下面的例子,我将向您展示如何使用排序操作w/属性,如大小。

最小到最大的大小(<)

    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属性名进行排序。以同样的方式,使用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
    }

可以为可选项设置二级排序。例如;可以显示带有元数据并按大小排序的图像。