사용자 정의 객체로 nsmutablearray를 어떻게 정렬합니까?
-
03-07-2019 - |
문제
내가하고 싶은 것은 매우 간단 해 보이지만 웹에서 답을 찾을 수는 없습니다. 나는있다 NSMutableArray
물체의 경우, 그들이 '사람'대상이라고 가정 해 봅시다. 나는 정렬하고 싶다 NSMutableArray
사람에 의해 NSDate
.
이 방법과 관련이 있다고 생각합니다.
NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];
Java에서는 내 객체를 비교할 수있게 만들거나 Collections.sort를 사용하여 인라인 사용자 정의 비교기와 함께 사용합니다 ... 지구상에서 어떻게 대상 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(id a, id b) {
NSDate *first = [(Person*)a birthDate];
NSDate *second = [(Person*)b birthDate];
return [first compare:second];
}];
성능
그만큼 -compare:
그리고 블록 기반 방법은 일반적으로 사용하는 것보다 상당히 빠릅니다. NSSortDescriptor
후자는 KVC에 의존합니다. 의 주요 장점 NSSortDescriptor
메소드는 코드가 아닌 데이터를 사용하여 정렬 순서를 정의하는 방법을 제공한다는 것입니다. 즉, 사용자가 정렬 할 수 있도록 항목을 쉽게 설정할 수 있습니다. NSTableView
헤더 행을 클릭하여
다른 팁
참조 NSMutableArray
방법 sortUsingFunction:context:
a를 설정해야합니다 비교하다 (유형의 두 객체를 취하는 함수 Person
, 당신은 두 가지를 비교하기 때문에 Person
물체) 및 a 문맥 매개 변수.
두 개체는 단지 인스턴스입니다 Person
. 세 번째 객체는 문자열 (예 : @”birthdate”입니다.
이 함수는 반환됩니다 NSComparisonResult
: 돌아옵니다 NSOrderedAscending
만약에 PersonA.birthDate
< PersonB.birthDate
. 돌아올 것입니다 NSOrderedDescending
만약에 PersonA.birthDate
> PersonB.birthDate
. 마지막으로 돌아올 것입니다 NSOrderedSame
만약에 PersonA.birthDate
== PersonB.birthDate
.
이것은 거친 의사 코드입니다. 한 날짜가 "낮은", "더"또는 "동등한"다른 날짜 (예 : Sec
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;
}
이 작업을 많이한다면 인라인은 아마도 이것을 약간 상승시킬 수 있습니다.
나는 블록을 사용하여 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;
추신 : 이것은 내림차순으로 정렬됩니다.
iOS 4에서 시작하여 정렬에 블록을 사용할 수도 있습니다.
이 특정 예에서는 배열의 객체에 '위치'메소드가 있다고 가정합니다. NSInteger
.
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];
참고 : "정렬 된"배열이 자동으로 표시됩니다.
나는 모든 것을 시도했지만 이것은 나를 위해 효과가있었습니다. 수업에는 "이름이"다른 수업이 있습니다.crimeScene
","그리고 "의 재산으로 분류하고 싶어crimeScene
".
이것은 매력처럼 작동합니다.
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
누락 된 단계가 있습니다 Georg Schölly의 두 번째 대답, 그러나 그것은 잘 작동합니다.
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptor:sortDescriptors];
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];
고마워요, 잘 작동합니다 ...
당신의 Person
객체는 방법을 구현해야합니다 compare:
다른 사람이 필요합니다 Person
대상과 반환 NSComparisonResult
두 객체 사이의 관계에 따라.
그러면 당신은 전화 할 것입니다 sortedArrayUsingSelector:
~와 함께 @selector(compare:)
그리고 그것은 완료해야합니다.
다른 방법이 있지만, 내가 아는 한 Cocoa-equiv는 Comparable
상호 작용. 사용 sortedArrayUsingSelector:
아마도 가장 고통스러운 방법 일 것입니다.
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 약간의 설명
을 위한 NSMutableArray
, 사용 sortUsingSelector
방법. 새 인스턴스를 만들지 않고도 정렬합니다.
목적을 위해 다음 일반 방법을 사용할 수 있습니다. 문제를 해결해야합니다.
//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];
배열을 정렬하는 경우 NSNumbers
, 당신은 1 개의 전화로 정렬 할 수 있습니다.
[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];
}];
또는 비교기의 본문은 1 라인으로 증류 될 수도 있습니다.
return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];
코드를 읽기 쉽고 디버깅하기가 더 쉽기 때문에 간단한 진술과 많은 임시 변수를 선호하는 경향이 있습니다. 컴파일러는 어쨌든 임시 변수를 최적화하므로 올인원 버전에는 이점이 없습니다.
나는 작은 카테고리 방법 라이브러리를 만들었습니다. LINQ에서 Objectivec, 그것은 이런 종류의 것을 더 쉽게 만듭니다. 사용 종류 키 선택기가있는 메소드는 다음을 정렬 할 수 있습니다. birthDate
다음과 같이 :
NSArray* sortedByBirthDate = [input sort:^id(id person) {
return [person birthDate];
}]
방금 사용자 지정 요구 사항을 기반으로 다중 레벨 정렬을 수행했습니다.
// 값을 정렬합니다
[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
나는 사용했다 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];
-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted
{
NSArray *sortedArray;
sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b)
{
return [a compare:b];
}];
return [sortedArray mutableCopy];
}
nsSortDescriptor를 사용하여 사용자 정의 객체와 NSMutableAreray를 정렬합니다.
NSSortDescriptor *sortingDescriptor;
sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
ascending:YES];
NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
정렬 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];
nscomparator를 사용하여 정렬하십시오
사용자 정의 객체를 정렬하려면 제공해야합니다. NSComparator
, 사용자 정의 객체를 비교하는 데 사용됩니다. 블록은 반환합니다 NSComparisonResult
값 두 객체의 순서를 나타내는 값. 전체 배열을 정렬하기 위해 NSComparator
다음 방식으로 사용됩니다.
NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
return [e1.firstname compare:e2.firstname];
}];
nsSortDescriptor를 사용하여 정렬합니다
예를 들어, 맞춤형 클래스의 인스턴스가 포함 된 배열이 있다고 가정 해 봅시다. 다음 예제는 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/
Swift의 프로토콜 및 기능 프로그래밍은 클래스가 비슷한 프로토콜을 준수하고 프로토콜에 필요한 메소드를 구현 한 다음 정렬 된 (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)
제 경우에는 "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
신속하게 배열을 정렬하십시오
을 위한 Swifty
아래 사람은 전 세계적으로 위의 목표를 달성하기위한 매우 깨끗한 기술입니다. 예제의 사용자 정의 클래스를 갖도록합시다 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
}
}
이제 가자 extension
의 Array
~을 위한 User
. 간단한 단어로는 배열에 대해서만 몇 가지 방법을 추가 할 수 있습니다. User
그 안에 물체.
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)
위의 방법
extension
인 경우에만 액세스 할 수 있습니다Array
유형입니다[User]
||Array<User>
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)
중첩 된 물체에 이와 같이 사용하십시오.
NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];
Lastroute는 하나의 객체이며 해당 객체는 TO Object를 유지하며, 객체는 마지막 이름 문자열 값을 유지합니다.
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"_strPrice"
ascending:sortFlag selector:@selector(localizedStandardCompare:)] ;
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(@"===============================");