Özel nesne dizisini özellik değerine göre sıralama


521

diyelim ki imageFile adında özel bir sınıfımız var ve bu sınıf iki özellik içeriyor.

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

birçoğu Array'da saklanıyor

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)

soru: nasıl görüntüleri dizi 'fileID' ASC veya DESC göre sıralayabilirim?


sıralama
ölçütü: KeyPath

Yanıtlar:


941

Öncelikle, yinelediğinizde yöntemleri çağırabilmeniz için Dizinizi yazılı bir dizi olarak bildirin:

var images : [imageFile] = []

Sonra şunları yapabilirsiniz:

Hızlı 2

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

Hızlı 3+

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

Yukarıdaki örnek verir desc sıralama düzeni


1
Dizi bildirim kısmı eksikti, Array <imageFile> hile yaptı.
mohacs

1
@AlexWayne CheckInAndOut NSManagedObjectadlı bir alt sınıfım var . Ve ayrı bir dosyada, bu tür nesneler için yazılan bir dizi ilan ettim ve sıralamaya çalıştığımda, Üye hatası bulunamadı . Neden bu olduğu hakkında bir düşünceniz var mı?
Isuru

3
Sorunumu buldum. Görünüşe göre dizi yazılan bir dizi değildi. Neyse yeni bir sorunum var. Bir diziyi birden çok özelliğe göre nasıl sıralayabilirim? Diyelim ki bir nesne dizisinde firstNameve gibi 2 özellik var . Önce sıralamak istiyorum sonra . Bunu nasıl yapabilirim? lastNamePersonfirstNamelastName
Isuru

12
şimdi yapman gerekiyor images.sortInPlace({ $0.fileID > $1.fileID })mu?
Taylor M

13
Herkes aynı şeyi merak ediyorsa: cevap desc order verecektir
Danny Wang

223

[ Swift 3 için sıralama (Güncellenme :) ile güncellendi ] Bu, takip eden bir kapanıştan faydalanıyor:

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

kullandığınız <veya >ASC veya DESC'ye bağlı olarak. Diziyi değiştirmek istiyorsanızimages , aşağıdakileri kullanın:

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

Bunu tekrar tekrar yapacaksanız ve bir işlev tanımlamayı tercih ediyorsanız, yollardan biri:

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

ve daha sonra şu şekilde kullanın:

images.sort(by: sorterForFileIDASC)

bunu dize ile nasıl dava edebilirim? uzunluğu dizesine göre sıralamak gerekir
Muneef M

@MuneefM sadece string1.length'e geri dön <string2.length
Surjeet Rajput

sortartık Xcode 8'deki bu sözdizimi ile derlenmiyor. Xcode 8 $0.fileID < $1.fileID, bir Bool CompareisonResult değil ürettiğini söylüyor .
Crashalot

3
Bu yanıtın kodu Xcode8'de iyi çalışıyor; bir hatanız varsa, yeni bir soru gönderin.
GoZoner

Bunu, karşılaştırmalara göre sıralamak için de kullanabilir miyim, örneğin dizi sıralamasının haftanın günlerine sahip olması? Öyleyse nasıl?
Kristofer

53

Neredeyse herkes ne kadar doğrudan verir , evrimi göstereyim:

Array'ın örnek yöntemlerini kullanabilirsiniz:

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

Ayıklamanın çalışma prensibi hakkında ayrıntılı açıklama için, bkz . Sıralı İşlev .


Bunu, karşılaştırmalara göre sıralamak için de kullanabilir miyim, örneğin dizi sıralamasının haftanın günlerine sahip olması? Öyleyse nasıl?
Kristofer

Okuyucuların "basitleştirilmiş" kapağın şifreli sözdizimini anlamalarını kabul etmek yerine, bir kapağın nasıl çalıştığını gösteren bir yanıt gönderdiğiniz için teşekkür ederiz!
user1118321

50

Hızlı 3

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

i bir tarih karşılaştırma ile denedim, çalışamadı. Herhangi bir fikir?
Ebru Güngör

NSDate veya String değil, geçerli swift 3 Date nesnesi.
Ebru Güngör

Tarihin hangi özelliğini karşılaştırıyorsunuz? Özellik, kullanılan işlevle karşılaştırılabilmelidir (
örneğimden

9
Bu, 2017'den sonraki tek yararlı cevaptır.
Fattie

@Fattie Ne demek istiyorsun? Doğru sözdizimipeople.sort { $0.email > $1.email }
Leo Dabus

43

Swift 5 ile, Arraydenilen iki yöntem vardır sorted()ve sorted(by:). İlk yöntem, sorted()şu bildirime sahiptir:

Koleksiyonun sıralanmış öğelerini döndürür.

func sorted() -> [Element]

İkinci yöntem, sorted(by:)şu açıklamaya sahiptir:

Öğeler arasındaki karşılaştırma olarak verilen yüklemi kullanarak sıralanan koleksiyonun öğelerini döndürür.

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

# 1. Karşılaştırılabilir nesneler için artan düzende sıralama

Koleksiyonunuzun içindeki öğe türü Comparableprotokole uyuyorsa sorted(), öğelerinizi artan düzende sıralamak için kullanabilirsiniz . Aşağıdaki Oyun Alanı kodu nasıl kullanılacağını gösterir 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. Karşılaştırılabilir nesneler için azalan düzende sıralama

Koleksiyonunuzun içindeki öğe türü Comparableprotokole uyuyorsa sorted(by:), öğelerinizi azalan sırada sıralamak için kullanmanız gerekir.

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.. Karşılaştırılamayan nesneler için artan veya azalan düzende sıralama

Koleksiyonunuzun içindeki öğe türü Comparableprotokole UYGUN DEĞİLSE sorted(by:), öğelerinizi artan veya azalan düzende sıralamak için kullanmanız gerekir.

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 da adlandırılan iki yöntem sağlar unutmayın sort()ve sort(by:)bir meslektaşları olarak sorted()ve sorted(by:)eğer yerinde koleksiyonunuzu sıralamak gerekir.


25

Swift 3.0'da

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

20

Ayrıca şöyle bir şey yapabilirsiniz

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

böylece resim diziniz sıralanmış olarak depolanır


19

2'den 4'e Hızlı

Orijinal yanıt, bazı özellikleri kullanarak bir dizi özel nesneyi sıralamaya çalıştı. Aşağıda, hızlı veri yapıları ile aynı davranışı gerçekleştirmenin birkaç kullanışlı yolunu göstereceğim!

Küçük şeyler yoldan çıktı, ImageFile'ı çok az değiştirdim. Bunu göz önünde bulundurarak, üç görüntü dosyası içeren bir dizi oluşturuyorum . Meta verilerin isteğe bağlı bir değer olduğuna dikkat edin, parametre olarak nil'den geçmesi beklenir.

 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 adlı bir özelliğe sahiptir. Aşağıdaki örnekler için size boyut gibi özellikler ile sıralama işlemlerinin nasıl kullanılacağını göstereceğim.

En küçükten en büyüğe (<)

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

büyükten küçüğe (>)

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

Sonra String özellik adını kullanarak sıralayacağız. Aynı şekilde, dizeleri karşılaştırmak için sort komutunu kullanın. Ancak iç bloğun bir karşılaştırma sonucu döndürdüğüne dikkat edin. Bu sonuç sıralamayı tanımlar.

AZ (.orderedAscending)

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

ZA (.orderedAzalan)

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

Sıralamak benim en sevdiğim yol, çoğu durumda biri isteğe bağlı özelliklere sahip olacak. Endişelenme, nil ile başa çıkmak zorunda kaldığımız sürece yukarıdakiyle aynı şekilde sıralayacağız! Üretimde;

Son olarak nil özellik değerleri ile dizimdeki tüm örnekleri zorlamak için bu kodu kullandım. Ardından varsayılan varsayılan değerleri kullanarak meta veriler sipariş edin.

    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
    }

Opsiyoneller için ikincil bir sıralama yapmak mümkündür. Örneğin; meta veri içeren ve boyuta göre sıralı resimler gösterilebilir.


1
Genellikle, kodun ne yapmak istediği ve başkalarını tanıtmadan sorunu neden çözdüğüne dair bir açıklama içeriyorsa, cevaplar çok daha yararlıdır.
Tom Aranda

Çok daha iyi.
Tom Aranda

18

İki alternatif

1) Orijinal diziyi sortInPlace ile sipariş etme

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

2) Sıralı diziyi saklamak için alternatif bir dizi kullanma

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

3
re 2) Boş bir dizi oluşturma ve onu sonraki satırda atmanın anlamı nedir? Kullanarak var assignmentsO : [Assignment]ya da kullanarak bir satırda birleştirmek istiyorumlet assignmentsO = self.assignments.sort({ $0.order < $1.order })
Hermann Klecker

2
Merhaba Hermann! Okunabilir ve etkili kod yazma arasında çok ince bir çizgi vardır. Bu durumda, tek nokta onu toplum için daha okunabilir hale getirmektir;) tadını çıkarın!
Bernauer

18

Swift 4.0, 4.1 ve 4.2 İlk olarak, aşağıda gösterildiği gibi imageFile () türünde değişken bir dizi oluşturdum

var arr = [imageFile]()

İmageFile () türünde değiştirilebilir nesne görüntüsü oluşturun ve özelliklere aşağıda gösterildiği gibi atayın

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

Şimdi, bu nesneyi dizi dizisine ekle

    arr.append(image)

Şimdi, aynı özellikleri değiştirilebilen nesneye, yani görüntüye farklı özellikler atayın

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

Şimdi tekrar dizi nesnesine resim nesnesi ekleyin

    arr.append(image)

Şimdi, biz uygulanacaktır Artan sırasını üzerine FileId dizi varış nesneleri mülk. Artan düzen için <sembolünü kullanın

 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

Şimdi, biz uygulanacaktır Azalan emri üzerine FileId dizi varış nesneleri mülk. Azalan düzen için > sembolünü kullanın

 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'de. & 4.2 Sıralı sipariş kullanımı için

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

8

Bu diziyi birden fazla yerde sıralayacaksanız, dizi türünüzü Karşılaştırılabilir yapmak mantıklı olabilir.

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

6

Özel nesneler kullanmıyorsanız, ancak Karşılaştırılabilir protokolü (Int, String vb.) Uygulayan değer türleri kullanıyorsanız bunu yapabilirsiniz:

myArray.sort(>) //sort descending order

Bir örnek:

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

hızlı 3'smyArray.sorted(by: >)
beryllium

6

Sıralı bir diziyi fileID özelliğinden şu şekilde döndürürsünüz:

Hızlı 2

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

Hızlı 3 VEYA 4

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

Swift 5.0

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

Works like a charm .. upvoted! (Pratik Prajapati, Ahmedabad)
NSPratik

4

Bunu böyle yapıyorum ve çalışıyor:

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


2

Orijinal özel nesne dizisini sıralamak istiyorsanız. Swift 2.1'de bunu yapmanın başka bir yolu

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

idTamsayı nerede ? Özellikler <için de aynı işleci kullanabilirsiniz String.

Buradaki bir örneğe bakarak kullanımı hakkında daha fazla bilgi edinebilirsiniz: Swift2: Yakındaki Müşteriler


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

students.sort(by: >)

print(students)

Baskılar: "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"


1

Hızlı 3 ve 4 ve 5

Küçük harf ve büyük harfle ilgili bir sorunum vardı

bu yüzden bu kodu yaptım

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

ve bundan sonra sortImages kullanın


0

KeyPath kullanarak sıralama

şöyle sıralayabilirsiniz KeyPath:

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

Bu küçük yararlı uzantıyı uygulayarak.

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

Hope Swift bunu yakın gelecekte dilin özüne ekliyor.


Bu, mutasyon yöntemi ile birlikte stackoverflow.com/a/46601105/2303865 burada zaten yanıtlanmıştır .
Leo Dabus

mutasyona public extension MutableCollection where Self: RandomAccessCollection { mutating func sort<T>(_ keyPath: KeyPath<Element, T>, by areInIncreasingOrder: (T, T) throws -> Bool) rethrows where T: Comparable { try sort { try areInIncreasingOrder($0[keyPath: keyPath], $1[keyPath: keyPath]) } }}
uğrayan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.