etc./StackOverFlow

사용자 정의 개체가 있는 NSMutableArray를 어떻게 정렬합니까?

청렴결백한 만능 재주꾼 2023. 4. 23. 02:47
반응형

질문자 :rustyshelf


내가 하고 싶은 것은 매우 간단해 보이지만 웹에서 답을 찾을 수 없습니다. 객체의 NSMutableArray 가 있으며 'Person' 객체라고 가정해 보겠습니다. NSDate Person.birthDate를 기준으로 NSMutableArray 를 정렬하고 싶습니다.

이 방법과 관련이 있다고 생각합니다.

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

Java에서는 내 개체가 Comparable을 구현하도록 만들거나 인라인 사용자 지정 비교기와 함께 Collections.sort를 사용합니다. 왜 Objective-C에서 이 작업을 수행합니까?



비교 방법

개체에 대한 비교 방법을 구현하거나 다음과 같이 하십시오.

 - (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(Person *a, Person *b) { return [a.birthDate compare:b.birthDate]; }];

성능

-compare: 및 블록 기반 방법은 일반적으로 NSSortDescriptor 를 사용하는 것보다 훨씬 빠릅니다. 후자는 KVC에 의존하기 때문입니다. NSSortDescriptor 메서드의 주요 이점은 코드가 아닌 데이터를 사용하여 정렬 순서를 정의하는 방법을 제공한다는 것입니다. 이를 통해 사용자가 헤더 행을 클릭하여 NSTableView


Community Wiki

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

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

두 객체는 Person 인스턴스일 뿐입니다. 세 번째 개체는 문자열입니다(예: @"birthDate").

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

이것은 대략적인 의사 코드입니다. 한 날짜가 다른 날짜와 "덜", "더 많이" 또는 "같다"는 것이 의미하는 바를 구체화해야 합니다(예: Epoch 이후 초 비교 등).

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

인라인을 사용하면 이 작업을 많이 수행하면 속도가 약간 빨라질 수 있습니다.


Alex Reynolds

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

또한 배열의 요소가 올바른 유형이 아닌 경우 수행할 작업을 결정해야 합니다. 이 예제에서는 방금 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;

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


Chris

iOS 4부터 정렬에 블록을 사용할 수도 있습니다.

NSInteger 를 반환하는 'position' 메서드가 있다고 가정합니다.

 NSArray *arrayToSort = where ever you get the array from... ; NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) { if ([obj1 position] > [obj2 position]) { return (NSComparisonResult)NSOrderedDescending; } if ([obj1 position] < [obj2 position]) { return (NSComparisonResult)NSOrderedAscending; } return (NSComparisonResult)NSOrderedSame; }; NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

참고: "정렬된" 배열은 자동 해제됩니다.


leviathan

나는 모든 것을 시도했지만 이것이 나를 위해 일했습니다. 클래스에 " crimeScene crimeScene "의 속성을 기준으로 정렬하려고 합니다.

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

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

Fernando Redondo

Georg Schölly의 두 번째 답변 에는 누락된 단계가 있지만 제대로 작동합니다.

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

// 복사하여 붙여넣을 때 시간이 낭비되어 sortedArrayUsingDescriptors에 ''가 없으면 실패했기 때문에 ''를 추가했습니다.


Manuel Spuhler

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

덕분에 잘쓰고 있습니다...


Hardik Darji

Person 개체는 다른 Person 개체를 사용하고 두 개체 간의 관계에 따라 NSComparisonResult compare: 와 같은 메서드를 구현해야 합니다.

그런 다음 @selector(compare:) 하여 sortedArrayUsingSelector: 를 호출하면 완료되어야 합니다.

다른 방법이 있지만 내가 아는 한 Comparable 인터페이스의 Cocoa와 동등한 것은 없습니다. sortedArrayUsingSelector: 사용하는 것이 아마도 가장 쉬운 방법일 것입니다.


freespace

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 약간의 설명


Community Wiki

NSMutableArray sortUsingSelector 메서드를 사용합니다. 새 인스턴스를 만들지 않고 제자리에 정렬합니다.


DenTheMan

목적에 따라 다음과 같은 일반 방법을 사용할 수 있습니다. 문제를 해결해야 합니다.

 //Called method -(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{ NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending]; [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]]; return arrDeviceList; } //Calling method [self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];

MD Aslam Ansari

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

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

배열의 개체( NSNumber 개체)가 비교 메서드를 구현하기 때문에 작동합니다. NSString 개체 또는 비교 메서드를 구현하는 사용자 지정 데이터 개체의 배열에 대해서도 동일한 작업을 수행할 수 있습니다.

다음은 비교기 블록을 사용하는 몇 가지 예제 코드입니다. 각 사전이 "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 개체는 비교 메서드를 구현하므로 훨씬 더 간단하게 다시 작성할 수 있습니다.

 #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]; }];

또는 비교기의 본문을 한 줄로 증류할 수도 있습니다.

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

나는 코드가 읽기 쉽고 디버그하기 쉽기 때문에 간단한 명령문과 많은 임시 변수를 선호하는 경향이 있습니다. 컴파일러는 어쨌든 임시 변수를 최적화하므로 일체형 버전에는 이점이 없습니다.


Dinesh_

NSSortDescriptor를 사용하여 사용자 정의 개체로 NSMutableArray를 정렬합니다.

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

Arvind Patel

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

Emile Khattar

저는 Linq to ObjectiveC 라고 하는 작은 범주 메서드 라이브러리를 만들었습니다. 키 선택기와 함께 정렬 방법을 사용하여 다음과 같이 birthDate

 NSArray* sortedByBirthDate = [input sort:^id(id person) { return [person birthDate]; }]

ColinE

방금 사용자 정의 요구 사항을 기반으로 다단계 정렬을 수행했습니다.

//값 정렬

 [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


Boobalan

일부 프로젝트에서 sortUsingFunction:: 을 사용했습니다.

 int SortPlays(id a, id b, void* context) { Play* p1 = a; Play* p2 = b; if (p1.score<p2.score) return NSOrderedDescending; else if (p1.score>p2.score) return NSOrderedAscending; return NSOrderedSame; } ... [validPlays sortUsingFunction:SortPlays context:nil];

roocell

NSMutableArray 정렬은 매우 간단합니다.

 NSMutableArray *arrayToFilter = [[NSMutableArray arrayWithObjects:@"Photoshop", @"Flex", @"AIR", @"Flash", @"Acrobat", nil] autorelease]; NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease]; for (NSString *products in arrayToFilter) { if (fliterText && [products rangeOfString:fliterText options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0) [productsToRemove addObject:products]; } [arrayToFilter removeObjectsInArray:productsToRemove];

Mohit

NSComparator를 사용하여 정렬

사용자 정의 개체를 정렬하려면 사용자 정의 개체를 비교하는 데 사용되는 NSComparator 블록은 두 객체의 순서를 나타내는 NSComparisonResult 따라서 전체 배열을 정렬하기 위해 NSComparator 는 다음과 같은 방식으로 사용됩니다.

 NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){ return [e1.firstname compare:e2.firstname]; }];

NSOrtDescriptor를 사용한 정렬
예를 들어 사용자 정의 클래스의 인스턴스를 포함하는 배열이 있고 Employee에는 이름, 성 및 연령 속성이 있다고 가정해 보겠습니다. 다음 예제에서는 배열 내용을 age 키를 기준으로 오름차순으로 정렬하는 데 사용할 수 있는 NSSortDescriptor를 만드는 방법을 보여줍니다.

 NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES]; NSArray *sortDescriptors = @[ageDescriptor]; NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

사용자 지정 비교를 사용하여 정렬
이름은 문자열이며 사용자에게 표시할 문자열을 정렬할 때는 항상 현지화된 비교를 사용해야 합니다. 종종 대소문자를 구분하지 않는 비교도 수행하려고 합니다. 다음은 성과 이름으로 배열을 정렬하는 (localizedStandardCompare:)를 사용한 예입니다.

 NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)]; NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)]; NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor]; NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

참조 및 자세한 논의는 https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html을 참조하십시오.
http://www.ios-blog.co.uk/tutorials/objective-c/how-to-sort-nsarray-with-custom-objects/


Aamir

Swift의 프로토콜과 함수형 프로그래밍을 사용하면 클래스가 Comparable 프로토콜을 따르도록 만들고 프로토콜에 필요한 메서드를 구현한 다음 sorted(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)

James Rochabrun

제 경우에는 "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

Emre Gürses

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)

Parth Barot

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

Array for User extension 할 수 있습니다. User 개체만 있는 배열에 대해서만 몇 가지 메서드를 추가할 수 있습니다.

 extension Array where Element: User { //This method only takes an order type. ie 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)

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


Syed Qamar Abbas

중첩된 객체에 대해 다음과 같이 사용합니다.

 NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)]; NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];

lastRoute는 하나의 객체이고 해당 객체는 to 객체를 보유하고 객체는 성 문자열 값을 보유합니다.


Sureshkumar Linganathan

스위프트 버전: 5.1

사용자 정의 구조체 또는 클래스가 있고 임의로 정렬하려는 경우 지정한 필드를 정렬하는 후행 클로저를 사용하여 sort()를 호출해야 합니다. 다음은 특정 속성을 기준으로 정렬하는 사용자 지정 구조체 배열을 사용하는 예입니다.

 struct User { var firstName: String } var users = [ User(firstName: "Jemima"), User(firstName: "Peter"), User(firstName: "David"), User(firstName: "Kelly"), User(firstName: "Isabella") ] users.sort { $0.firstName < $1.firstName }

제자리에서 정렬하는 대신 정렬된 배열을 반환하려면 다음과 같이 sorted()를 사용하십시오.

 let sortedUsers = users.sorted { $0.firstName < $1.firstName }

sDev

 let sortedUsers = users.sorted { $0.firstName < $1.firstName }

Manish Kumar

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(@"===============================");

Community Wiki

출처 : http:www.stackoverflow.com/questions/805547/how-do-i-sort-an-nsmutablearray-with-custom-objects-in-it

반응형