속성 값으로 사용자 정의 객체 배열을 정렬하는 방법


521

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'ASC 또는 DESC로 이미지 배열을 정렬 할 수 있습니까?


KeyPath를 기준으로 정렬 stackoverflow.com/a/46601105/2303865
Leo Dabus

답변:


941

먼저 배열을 유형이 지정된 배열로 선언하면 반복 할 때 메소드를 호출 할 수 있습니다.

var images : [imageFile] = []

그런 다음 간단하게 수행 할 수 있습니다.

스위프트 2

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

스위프트 3+

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

위의 예는 desc 정렬 순서를 제공합니다


1
배열 선언 부분이 누락되어 Array <imageFile> 트릭을 수행했습니다.
mohacs

1
@AlexWayne CheckInAndOut NSManagedObject이라는 하위 클래스가 있습니다 . 그리고 별도의 파일에,이 유형의 개체에 대한 형식화 된 배열을 선언 한 내가하려고 할 때 분류 를, 내가 얻을 멤버 찾을 수 없습니다 오류가 발생했습니다. 이것이 왜 그런지 아십니까?
Isuru

3
내 문제를 찾았습니다. 분명히 배열은 유형이 지정된 배열이 아닙니다. 어쨌든 새로운 문제가 있습니다. 여러 속성으로 배열을 정렬하려면 어떻게해야합니까? 객체 의 배열 firstName과 같은 2 개의 속성이 있다고 가정 해보십시오 . 먼저 정렬 한 다음 정렬하고 싶습니다 . 어떻게해야합니까? lastNamePersonfirstNamelastName
Isuru

12
이제해야합니까 images.sortInPlace({ $0.fileID > $1.fileID })?
Taylor M

13
누군가가 똑같은 것을 궁금해하는 경우 : 답변은 desc 명령을 줄 것이다
Danny Wang

223

[ sort (by :)를 사용하여 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)

문자열로 어떻게 이것을 고소 할 수 있습니까? 길이에 따라 문자열을 정렬해야합니다
Muneef M

@MuneefM은 string2.length string1.length를 <반환
Surjeet이 라

sort더 이상 Xcode 8에서이 구문으로 컴파일하지 않습니다. Xcode 8에 따르면 $0.fileID < $1.fileIDBool not ComparisonResult가 생성됩니다.
Crashalot

3
이 답변의 코드는 Xcode8에서 잘 작동합니다. 오류가 있으면 새 질문을 게시하십시오.
GoZoner

예를 들어 요일별로 배열을 정렬하는 등 비교를 기준으로 정렬 할 수 있습니까? 그렇다면 어떻게?
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 })

날짜 비교로 시도했지만 작동하지 못했습니다. 어떤 생각?
Ebru Güngör 2016

NSDate 또는 String이 아니며 현재 빠른 3 Date 객체입니다.
Ebru Güngör

Date의 어떤 속성을 비교하고 있습니까? 이 건물은 (내 예에서보다 더)을 사용하는 기능과 비교 될 수 있어야합니다
quemeful

9
2017 년 이후로 유일하게 유용한 답변입니다.
Fattie

@Fattie 무슨 뜻인가요? 올바른 구문은 다음과 같습니다people.sort { $0.email > $1.email }
Leo Dabus

43

Swift 5 Array에는 sorted()and 라는 두 가지 메소드가 sorted(by:)있습니다. 첫 번째 방법 sorted()은 다음과 같은 선언입니다.

컬렉션의 요소를 정렬하여 반환합니다.

func sorted() -> [Element]

두 번째 방법 sorted(by:)은 다음과 같은 선언입니다.

주어진 술어를 요소 간의 비교로 사용하여 정렬 된 콜렉션의 요소를 리턴합니다.

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

#1. 비교 가능한 객체에 대해 오름차순으로 정렬

컬렉션 내의 요소 유형이 Comparable프로토콜을 따르는 경우 sorted()요소를 오름차순으로 정렬하는 데 사용할 수 있습니다 . 다음 놀이터 코드는 사용 방법을 보여줍니다 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]
 */

#삼. 비교할 수없는 객체의 오름차순 또는 내림차순으로 정렬

컬렉션 내의 요소 유형이 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]
 */

스위프트는 또한라는 두 가지 방법을 제공합니다 sort()sort(by:)의 대응으로 sorted()하고 sorted(by:)경우에 당신이 자리에서 컬렉션을 정렬 할 필요가있다.


25

스위프트 3.0

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

20

당신은 또한 같은 것을 할 수 있습니다

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

따라서 이미지 배열은 정렬 된 것으로 저장됩니다


19

스위프트 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 속성 이름을 사용하여 정렬합니다. 같은 방식으로 정렬을 사용하여 문자열을 비교하십시오. 그러나 내부 블록은 비교 결과를 반환합니다. 이 결과는 정렬을 정의합니다.

AZ (. 순 오름차순)

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

ZA (. 순 내림차순)

    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
일반적으로 코드의 목적과 다른 언어를 도입하지 않고 문제를 해결하는 이유에 대한 설명이 포함되어 있으면 답변이 훨씬 유용합니다.
Tom Aranda

훨씬 더 좋습니다.
Tom Aranda

18

두 가지 대안

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) 빈 배열을 만들어서 다음 줄에서 버리는 요점은 무엇입니까? 내가 사용 있습니다 sugest 것 var assignmentsO : [Assignment]또는 사용하여 하나 개의 라인으로 결합let assignmentsO = self.assignments.sort({ $0.order < $1.order })
헤르만 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.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.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

스위프트 4.1. & 4.2 정렬 순서 사용

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

8

이 배열을 둘 이상의 위치에서 정렬하려는 경우 배열 유형을 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]"

6

사용자 정의 객체를 사용하지 않고 비교 가능한 프로토콜 (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

스위프트 3에서 그것은myArray.sorted(by: >)
베릴륨

6

다음과 같은 방법으로 fileID 속성에서 정렬 된 배열을 반환합니다.

스위프트 2

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

스위프트 3 또는 4

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

스위프트 5.0

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

매력처럼 작동합니다 .. 공감! (Pratik Prajapati, Ahmedabad)
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 : 인근 고객


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

students.sort(by: >)

print(students)

인쇄 : "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"


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

Hope Swift는 언어의 핵심에서 가까운 미래에 이것을 추가합니다.


이것은 이미 mutating 방법과 함께 stackoverflow.com/a/46601105/2303865에서 답변되었습니다 .
Leo Dabus

변경 버전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]) } }}
Leo Dabus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.