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


当前回答

在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
    }

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

如果数组元素符合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语法是我们指定关键路径的方式。您可以根据需要扩展比较器列表。

如果你要在多个地方对这个数组排序,让你的数组类型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]"

斯威夫特3、4、5所示

    struct imageFile  {
        var fileName = String()
        var fileID = Int()
    }
    
    //append objects like this
    var arrImages = [imageFile]()
    arrImages.append(.init(fileName: "Hello1.png", fileID: 1))
    arrImages.append(.init(fileName: "Hello3.png", fileID: 3))
    arrImages.append(.init(fileName: "Hello2.png",fileID: 2))

    
    //array sorting using below code
    let sortImagesArr = arrImages.sorted(by: {$0.fileID < $1.fileID})
    print(sortImagesArr)
    
    //output
    
    imageFile(fileName: "Hello1.png", fileID: 1),
    imageFile(fileName: "Hello2.png", fileID: 2),
    imageFile(fileName: "Hello3.png", fileID: 3)

Swift 4.0, 4.1和4.2:

首先,我创建了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"

现在,再次将image object追加到数组arr中

arr.append(image)

现在,我们将对数组arr对象中的fileId属性应用升序。使用<符号按升序排列

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

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

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和4.2中,用于排序使用

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