ios - sortedarrayusingcomparator - xcode array sort




NSMutableArray를 사용자 정의 객체로 정렬하려면 어떻게합니까? (17)

내가하고 싶은 일은 아주 단순 해 보이지만 웹에서 답을 찾을 수는 없습니다. 객체의 NSMutableArray 를 가지고 있고 그것들이 'Person'객체라고 가정 해 봅시다. NSDate Person.birthDate에 의해 NSMutableArray 를 정렬하려고합니다.

나는 그것이이 방법과 관련이 있다고 생각한다.

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

Java에서 내 개체를 Comparable로 구현하거나 인라인 사용자 지정 비교기로 Collections.sort를 사용합니다. Objective-C에서이 작업을 수행하는 방법은 무엇입니까?


Swift에서 배열 정렬

Swifty Person은 아래의 목표를 달성하기위한 매우 깨끗한 기술입니다. 몇 가지 속성을 가진 User 의 예제 사용자 정의 클래스가 있습니다.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

이제 createdDate 를 기준으로 오름차순 또는 내림차순으로 정렬해야하는 배열이 있습니다. 그래서 날짜 비교를위한 함수를 추가 할 수 있습니다.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

이제 User 위한 Array extension 을 허용하십시오. 간단히 말해, User 객체 만있는 Array에 대해서만 몇 가지 메소드를 추가 할 수 있습니다.

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

오름차순의 사용법

let sortedArray = someArray.sortUserByDate(.orderedAscending)

내림차순 사용

let sortedArray = someArray.sortUserByDate(.orderedAscending)

동일한 주문에 대한 사용

let sortedArray = someArray.sortUserByDate(.orderedSame)

Array[User] || 유형 인 경우에만 extension 위의 메소드에 액세스 할 수 있습니다. Array<User>


메소드 비교

당신은 당신의 객체를위한 compare-method를 구현한다 :

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (더 나은)

또는 보통 더 나은 :

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

배열에 하나 이상을 추가하여 여러 키로 쉽게 정렬 할 수 있습니다. 커스텀 콤퍼레이터 메소드를 사용하는 것도 가능합니다. 문서를보십시오 .

블록 (빛나는!)

Mac OS X 10.6 및 iOS 4 이후 블록을 사용하여 정렬 할 수도 있습니다.

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

공연

후자는 KVC를 사용 NSSortDescriptor 때문에 NSSortDescriptor 를 사용하는 것보다 -compare: 및 블록 기반 메서드는 일반적으로 훨씬 빠릅니다. NSSortDescriptor 메서드의 가장 큰 장점은 코드가 아닌 데이터를 사용하여 정렬 순서를 정의 할 수있는 방법을 제공한다는 것입니다. 예를 들어 머리글 행을 클릭하여 NSTableView 를 정렬 할 수 있도록 설정할 수 있습니다.


Swift의 프로토콜과 함수형 프로그래밍을 사용하면 클래스가 Comparable 프로토콜을 준수하도록하고 프로토콜에 필요한 메소드를 구현 한 다음 정렬 된 (by :) 고차 함수를 사용하여 정렬 된 배열을 사용할 필요없이 쉽게 만들 수 있습니다 그런데 배열을 변경할 수 있습니다.

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)

iOS 4 블록을 저장하면됩니다 :)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html 설명이 약간 있습니다.


sortDescriptor를 생성 한 다음 아래처럼 sortDescriptor를 사용하여 nsmutablearray를 정렬 할 수 있습니다.

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)

나는 모든 것을 시도했다. 그러나 이것은 나를 위해 일했다. 어떤 클래스에서는 " crimeScene "이라는 또 다른 클래스가 crimeScene , " crimeScene "속성으로 정렬하려고합니다.

이것은 매력처럼 작동합니다.

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

방금 사용자 지정 요구 사항을 기반으로 여러 수준의 정렬을 수행했습니다.

// 값을 정렬합니다.

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec


블록을 사용하여 iOS 4에서이 작업을 수행했습니다. ID에서 내 클래스 유형으로 배열의 요소를 캐스팅해야했습니다. 이 경우 점수라는 속성이있는 점수라는 클래스였습니다.

또한 배열의 요소가 올바른 형식이 아닌 경우 수행 할 작업을 결정해야합니다.이 예제에서는 NSOrderedSame 반환했지만 예외는 있지만 코드에서는 예외가 있습니다.

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

추신 : 이것은 내림차순으로 정렬됩니다.


필자의 경우 "sortedArrayUsingComparator"를 사용하여 배열을 정렬합니다. 아래 코드를보십시오.

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

또한 나의 목표는,

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end

Georg Schölly의 두 번째 대답 에서 빠진 단계가 있지만 잘 작동합니다.

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptor:sortDescriptors];

NSMutableArray 메서드 sortUsingFunction:context: 참조하십시오 sortUsingFunction:context:

두 개의 객체 (두 개의 Person 객체를 비교하기 때문에 Person 유형의 객체)와 컨텍스트 매개 변수를 취하는 비교 함수를 설정해야합니다.

두 객체는 Person 인스턴스입니다. 세 번째 객체는 @ "birthDate"와 같은 문자열입니다.

이 함수는 NSComparisonResult 반환합니다. PersonA.birthDate < PersonB.birthDate 경우 NSOrderedAscending 반환합니다. PersonA.birthDate > PersonB.birthDate 경우 NSOrderedDescending 을 반환합니다. 마지막으로 PersonA.birthDate == PersonB.birthDate 경우 NSOrderedSame 을 반환합니다.

거친 가상 코드입니다. 당신은 한 날짜가 다른 날짜에 "덜", "더"또는 "동등"하다는 의미가 무엇인지 육체화해야합니다 (예 : 초를 비교 한 것 등).

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

보다 작은 것을 원한다면 삼항 연산자를 사용할 수 있습니다 :

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

당신이 이것을 많이한다면, 인라이닝은 아마도 약간의 속도를 낼 수 있습니다.


NSMutableArray 의 경우에는 sortUsingSelector 메소드를 사용하십시오. 새 인스턴스를 만들지 않고도 it-place를 정렬합니다.


NSNumbers 의 배열을 정렬하는 경우에는 1 회의 호출로 정렬 할 수 있습니다.

[arrayToSort sortUsingSelector: @selector(compare:)];

배열 ( NSNumber 개체)의 개체가 compare 메서드를 구현하기 때문에 작동합니다. NSString 객체 나 심지어 compare 메소드를 구현하는 커스텀 데이터 객체의 배열에 대해서도 똑같이 할 수있다.

다음은 비교기 블록을 사용하는 몇 가지 예제 코드입니다. 각 사전이 "sort_key"키에 숫자를 포함하는 사전 배열을 정렬합니다.

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

위의 코드는 각 정렬 키에 대한 정수 값을 가져 와서 비교하는 작업을 수행하는 방법을 보여줍니다. NSNumber 객체는 compare 메소드를 구현하기 때문에 훨씬 간단하게 다시 작성할 수 있습니다.

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

또는 비교기의 몸체를 1 줄까지 증류 할 수 있습니다.

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

나는 코드가 읽기 쉽고 디버깅하기 쉽기 때문에 간단한 문장과 많은 임시 변수를 선호하는 경향이있다. 컴파일러는 어쨌든 임시 변수를 최적화하여 올인원 버전에 아무런 이점도 없습니다.


Person 객체는 다른 Person 객체를 취하는 compare: 메소드를 구현해야하며 두 객체 간의 관계에 따라 NSComparisonResult 반환 NSComparisonResult 합니다.

그런 다음 sortedArrayUsingSelector:@selector(compare:) 와 호출하면 완료됩니다.

다른 방법이 있지만, 필자가 아는 한 Comparable 인터페이스의 코코아 -equiv는 없다. sortedArrayUsingSelector: 사용하기 sortedArrayUsingSelector: 아마도 가장 고통 sortedArrayUsingSelector: 방법 일 것입니다.


-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}

NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

고마워, 잘하고있어.





nsmutablearray