ios - objective - sortedarrayusingcomparator




Как отсортировать NSMutableArray с пользовательскими объектами в нем? (17)

Метод сравнения

Либо вы реализуете метод сравнения для своего объекта:

- (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: и block-based будут в целом более NSSortDescriptor , чем использование NSSortDescriptor поскольку последний полагается на KVC. Основное преимущество метода NSSortDescriptor заключается в том, что он предоставляет способ определения вашего порядка сортировки с использованием данных, а не кода, что упрощает, например, настраивать вещи, чтобы пользователи могли сортировать NSTableView , щелкая по строке заголовка.

То, что я хочу сделать, кажется довольно простым, но я не могу найти ответы в Интернете. У меня есть NSMutableArray объектов, и, допустим, это объекты Person. Я хочу сортировать NSMutableArray по Person.birthDate, который является NSDate .

Я думаю, что это имеет какое-то отношение к этому методу:

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

Теперь давайте иметь 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>


В моем случае я использую «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

Вам нужно создать sortDescriptor, а затем вы можете отсортировать nsmutablearray с помощью sortDescriptor, как показано ниже.

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

Вы можете использовать следующий общий метод для своей цели. Он должен решить вашу проблему.

//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];

Для NSMutableArray используйте метод sortUsingSelector . Он сортирует это место, не создавая новый экземпляр.


Начиная с iOS 4 вы также можете использовать блоки для сортировки.

В этом конкретном примере я предполагаю, что объекты в вашем массиве имеют метод «position», который возвращает 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];

Примечание: «отсортированный» массив будет автореализован.


Объекты Person должны реализовать метод, например compare: который принимает другой объект Person , и возвращает NSComparisonResult соответствии с отношением между двумя объектами.

Затем вы должны вызвать sortedArrayUsingSelector: с @selector(compare:) и это должно быть сделано.

Есть и другие способы, но, насколько я знаю, не существует Cocoa-equiv интерфейса Comparable . Использование sortedArrayUsingSelector: это, вероятно, самый безболезненный способ сделать это.


См. Метод sortUsingFunction:context:

Вам нужно будет настроить функцию сравнения, которая принимает два объекта (типа Person , поскольку вы сравниваете два объекта Person ) и параметр контекста .

Эти два объекта являются только экземплярами Person . Третий объект - это строка, например @ "birthDate".

Эта функция возвращает NSComparisonResult : она возвращает NSOrderedAscending если PersonA.birthDate < PersonB.birthDate . Он вернет NSOrderedDescending если PersonA.birthDate > PersonB.birthDate . Наконец, он вернет NSOrderedSame если PersonA.birthDate == PersonB.birthDate .

Это грубый псевдокод; вам нужно будет определить, что означает для одной даты «меньше», «больше» или «равно» другой дате (например, сравнение секунд-с-эпохи и т. д.):

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 очень проста:

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

Я пробовал все, но это сработало для меня. В классе у меня есть еще один класс под названием « 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


Я создал небольшую библиотеку категорийных методов, называемую Linq to ObjectiveC , что упрощает эту задачу. Используя метод sort с помощью селектора ключей, вы можете сортировать по birthDate следующим образом:

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

Во втором ответе Георга Шёлли есть недостающий шаг, но он отлично работает.

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

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