プロパティ値でカスタムオブジェクトの配列を並べ替える方法を迅速に


521

imageFileという名前のカスタムクラスがあり、このクラスに2つのプロパティが含まれているとします。

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で画像配列をソートするにはどうすればよいですか?


回答:


941

最初に、配列を型付き配列として宣言し、反復するときにメソッドを呼び出せるようにします。

var images : [imageFile] = []

次に、単に行うことができます:

スウィフト2

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

Swift 3以上

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

上記の例は、descソート順を示しています


1
配列宣言の部分がありませんでした、それはトリックArray <imageFile>を行いました。
mohacs 2014年

1
@AlexWayne CheckInAndOutというNSManagedObjectサブクラスがあります。そして、別のファイルで、この型のオブジェクトの型付き配列を宣言しました。それをソートしようとすると、メンバー見つかりませんというエラーが発生します。これはなぜですか?
Isuru 2014

3
問題が見つかりました。どうやら配列は型付き配列ではなかったようです。とにかく、新しい問題があります。配列を複数のプロパティでソートするにはどうすればよいですか?オブジェクトの配列のような2つのプロパティがあるfirstNamelastNamePersonます。最初に並べ替えをfirstName行い、次に並べ替えを行いlastNameます。どうすればこれを行うことができますか?
Isuru

12
あなたは今やる必要がありimages.sortInPlace({ $0.fileID > $1.fileID })ますか?
テイラーM

13
誰かが同じことを疑問に思っている場合:答えは説明の順序になります
Danny Wang

223

[ sort(by :)を使用してSwift 3用に更新 ]これは、末尾のクロージャーを利用します

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

どこで使用する<>、またはそれぞれASCまたはDESCに依存します。 配列を変更する場合imagesは、次を使用します。

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

これを繰り返して関数を定義したい場合、1つの方法は次のとおりです。

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

そして次のように使用します:

images.sort(by: sorterForFileIDASC)

どうすればこれを文字列で訴えることができますか?文字列をその長さで並べ替える必要があります
Muneef M

@MuneefMは単にstring1.length <string2.lengthを返す
Surjeet Rajput

sortXcode 8では、この構文を使用してコンパイルできなくなりまし$0.fileID < $1.fileIDた。Xcode8は、ComparisonResultではなくBoolを生成すると言っています。
Crashalot 2016

3
この回答のコードはXcode8で正常に動作します。エラーが発生した場合は、新しい質問を投稿してください。
GoZoner 2016

これを使用して、たとえば、配列を曜日でソートするなど、比較でソートすることもできますか?もしそうなら?
Kristofer

53

ほとんど誰もがどのように与える直接、進化を示しましょう。

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

ソートの動作原理についての詳細な説明については、ソート関数を参照してください。


これを使用して、たとえば、配列を曜日でソートするなど、比較でソートすることもできますか?もしそうなら?
Kristofer

読者が「簡略化された」クロージャーの不可解な構文を理解していると想定する代わりに、クロージャーがどのように機能するかを示す回答を投稿していただきありがとうございます。
user1118321

50

スウィフト3

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

私は日付比較でこれを試しました、それを機能させることができませんでした。何か案が?
EbruGüngör2016年

NSDateまたはStringではなく、現在のSwift 3 Dateオブジェクト。
EbruGüngör2016年

日付のどのプロパティを比較していますか?プロパティは、使用されている関数と比較できる必要があります(この例よりも大きい)
キューメフル

9
これは2017年以降の唯一の有用な回答です。
Fattie

@Fattieどういう意味ですか?正しい構文は次のとおりですpeople.sort { $0.email > $1.email }
レオDabus

43

Swift 5では、およびArrayという2つのメソッドがsorted()ありsorted(by:)ます。最初のメソッドsorted()は次の宣言を持っています:

ソートされたコレクションの要素を返します。

func sorted() -> [Element]

2番目のメソッド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]
 */

スウィフトはとも呼ばれる2つのメソッドを提供することに注意してくださいsort()sort(by:)のカウンターパートとしてsorted()及びsorted(by:)もしあなたがその場であなたのコレクションをソートする必要があります。



20

次のようなこともできます

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

画像配列はソートされた状態で保存されます


19

Swift 2から4

元の答えは、いくつかのプロパティを使用してカスタムオブジェクトの配列をソートすることでした。以下に、迅速なデータ構造で同じ動作を行ういくつかの便利な方法を示します。

ささいなことで、ImageFileを少しだけ変更しました。それを念頭に置いて、3つのイメージファイルを含む配列を作成します。メタデータはオプションの値であり、パラメーターとして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という名前のプロパティがあります。次の例では、サイズなどのプロパティを使用した並べ替え操作の使用方法を示します。

最小から最大サイズ(<)

    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を使用して文字列を比較します。しかし、内部ブロックが比較結果を返すことに注意してください。この結果はソートを定義します。

AZ(.orderedAscending)

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

ZA(.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
    }

オプションの2次ソートを行うことができます。例えば; サイズで並べ替えられたメタデータ付きの画像を表示できます。


1
一般に、コードに意図されていること、および他の人を紹介することなく問題を解決する理由の説明が含まれている場合、回答ははるかに役立ちます。
トム・アランダ

はるかに良い。
トム・アランダ

18

2つの選択肢

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
re 2)空の配列を作成し、それを次の行で破棄する意味は何ですか?私は使用var assignmentsO : [Assignment]することをお勧めしますまたはそれを1行に結合しますlet assignmentsO = self.assignments.sort({ $0.order < $1.order })
Hermann Klecker

2
こんにちはヘルマン!読みやすく効率的なコードを書くことの間には非常に細い線があります。この場合、唯一のポイントは、コミュニティで読みやすくすることです;)お楽しみください!
Bernauer 2016年

18

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"

さて、再び画像オブジェクトを配列arrに追加します

    arr.append(image)

今、私たちは、適用される順序を昇順FILEIDの配列arrオブジェクト内のプロパティ。昇順には<記号を使用します

 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

今、私たちは、適用される順序を降順に上FILEIDの配列arrオブジェクト内のプロパティ。>記号を使用して降順

 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
}

8

この配列を複数の場所で並べ替える場合は、配列の型を比較可能にすることは意味があります。

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

カスタムオブジェクトを使用せず、代わりに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

Swift 3の場合myArray.sorted(by: >)
ベリリウム

6

次の方法で、fileIDプロパティからソートされた配列を返します。

スウィフト2

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

Swift 3または4

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

Swift 5.0

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

魅力のように動作します。(プラティクプラジャパティ、アーメダバード)
NSPratik

4

私はこのようにしてそれが機能します:

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


2

カスタムオブジェクトの元の配列を並べ替える場合。これはSwift 2.1でこれを行う別の方法です

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

id整数はどこにありますか。プロパティにも同じ<演算子を使用できますString

使用例については、こちらの例をご覧ください 。Swift2:近隣のお客様



1

スウィフト3&4&5

小文字と大文字に関連する問題がありました

だから私はこのコードをやった

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

その後、sortedImagesを使用します


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が言語のコアにこれを追加することを期待しています。


これは、こちらのStackoverflow.com/a/46601105/2303865ですでに回答されてい ます。
レオダバス

変異バージョン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]) } }}
レオダバス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.