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

1268

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

Я думаю, что это как-то связано с этим методом:

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

В Java я хотел бы, чтобы мой объект реализовывал Comparable, или использовал Collections.sort со встроенным пользовательским компаратором ... как же это сделать в Objective-C?

rustyshelf
источник

Ответы:

2299

Сравнить метод

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

- (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качестве последнего полагается на КВЦ. Основное преимущество NSSortDescriptorметода заключается в том, что он предоставляет способ определения порядка сортировки с использованием данных, а не кода, что позволяет, например, легко настроить объекты, чтобы пользователи могли сортировать их NSTableView, щелкая строку заголовка.

Georg Schölly
источник
66
В первом примере есть ошибка: вы сравниваете переменную экземпляра birthDate в одном объекте с самим другим объектом, а не с его переменной birthDate.
Мартин Гьялдбек
90
@ Мартин: Спасибо! Забавно, что никто не заметил, прежде чем я получил 75 голосов за это.
Георг Шолли
76
Поскольку это общепринятый ответ и, следовательно, большинство пользователей считают его окончательным, было бы полезно добавить третий, основанный на блоках пример, чтобы пользователи знали, что он тоже существует.
jpswain
6
@ orange80: я пробовал это. У меня больше нет Mac, поэтому было бы неплохо, если бы вы взглянули на код.
Георг Шолли
11
Если у вас есть, NSMutableArrayя предпочитаю использовать методы sortUsingDescriptors, sortUsingFunctionили sortUsingSelector. Поскольку массив изменчив, мне обычно не нужна отсортированная копия.
Стефан
109

Смотрите NSMutableArrayметод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;
}

Встраивание может, возможно, немного ускорить это, если вы делаете это много.

Алекс Рейнольдс
источник
9
Использование sortUsingFunction: context: является, вероятно, наиболее точным способом и определенно самым нечитаемым.
Георг Шолли
12
В этом нет ничего плохого, но я думаю, что теперь есть гораздо лучшие альтернативы.
Георг Шолли
6
Возможно, но я не думаю, что это было бы менее читабельным для кого-то из фона Java, который мог бы искать что-то похожее на абстрактный класс Java-компаратора, который реализует сравнение (Тип obj1, Тип obj2).
Алекс Рейнольдс
5
Я понимаю, что некоторые из вас ищут любую причину, чтобы критиковать этот совершенно прекрасный ответ, даже если эта критика имеет очень мало технических достоинств. Weird.
Алекс Рейнольдс
1
@ Яр: Либо вы можете использовать решение, которое я предоставил в первом абзаце, либо использовать несколько дескрипторов сортировки. sortedArrayUsingDescriptors: принимает массив дескрипторов сортировки в качестве аргумента.
Георг Шолли
62

Я сделал это в iOS 4, используя блок. Пришлось привести элементы моего массива из id к типу моего класса. В данном случае это был класс Score с свойством points.

Также вам нужно решить, что делать, если элементы вашего массива не правильного типа, для этого примера я только что вернулся 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;

PS: это сортировка по убыванию.

Крис
источник
6
Вам на самом деле не нужны приведения «(Score *)», вы можете просто выполнить «Score * s1 = obj1;» потому что id с радостью приведёт к чему угодно без предупреждения от компилятора :-)
jpswain
right orange80 downcastingне требует приведения перед слабой переменной.
thesummersign
Вы должны сортировать ноль против не-ноль в верхней или нижней части последовательно, поэтому конец умолчанию возвращают может бытьreturn ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending))
Скотт Corscadden
хех Крис, я пробовал этот код, я обновлял свою программу ... впервые я исправляю работу, получаю вывод в порядке убывания ... но когда я обновляюсь (выполняю тот же код с теми же данными), это изменилось порядок, он не нисходящий. Скажем, у меня 4 объекта в моем массиве, 3 объекта с одинаковыми данными, 1 отличается.
Никеш К
Если вы действительно ожидаете объекты, которые не относятся к классу «Оценка», вам нужно отсортировать их немного более тщательно. В противном случае вы столкнетесь с ситуацией, когда другое == оценка1 <оценка2 == другое, что является непоследовательным и может привести к проблемам. Вы можете вернуть значение, которое подразумевает сортировку объектов Score перед всеми остальными объектами, а все остальные объекты сортируются равными друг другу.
gnasher729
29

Начиная с 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];

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

левиафан
источник
26

Я перепробовал все, но это сработало для меня. В классе у меня есть другой класс с именем " crimeScene", и я хочу отсортировать по свойству " crimeScene".

Это работает как шарм:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
Фернандо Редондо
источник
21

Во втором ответе Георга Шолли пропущен шаг , но тогда он работает нормально.

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

// добавил 's', потому что время было потрачено впустую, когда я скопировал и вставил, и это не удалось без 's' в sortedArrayUsingDescriptors

Мануэль Спулер
источник
Вызов метода на самом деле "sortedArrayUsingDescriptors:", с 's' в конце.
CIFilter
19
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Спасибо работает нормально ...

Хардик Даржи
источник
17

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

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

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

свободное место
источник
9

Блоки 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 немного описания

Константин Соколинский
источник
8

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

DenTheMan
источник
Просто обновление: я тоже искал что-то, что сортировало изменяемый массив на месте, теперь есть «sortUsing» эквивалентные методы для всех методов «sortedArrayUsing», начиная с iOS 7. Например sortUsingComparator:.
Jmathew
7

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

//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];
Доктор медицины Аслам Ансари
источник
6

Если вы просто сортируете массив 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];
 }];

или же тело компаратора может быть перегонено до 1 строки:

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

Я предпочитаю простые операторы и множество временных переменных, потому что код легче читать и легче отлаживать. Компилятор оптимизирует временные переменные так или иначе, поэтому у версии «все в одной строке» нет никаких преимуществ.

Dinesh_
источник
5

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

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]
Coline
источник
Вы должны назвать это « LINQ to Objective-C ».
Питер Мортенсен
5

Я только что сделал многоуровневую сортировку на основе пользовательских требований.

// сортируем значения

    [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
источник
5

Я использовал 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
источник
5

Вы используете NSSortDescriptor для сортировки NSMutableArray с пользовательскими объектами

 NSSortDescriptor *sortingDescriptor;
 sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                       ascending:YES];
 NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
Арвинд Патель
источник
4
-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}
Эмиль Хаттар
источник
зачем передавать в изменяемый массив, когда возвращается новый массив. зачем вообще создавать обертку?
Викингосегундо
3

Сортировка 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];
Мохит
источник
2

Сортировка с использованием NSComparator

Если мы хотим отсортировать пользовательские объекты, нам нужно предоставить данные NSComparator, которые используются для сравнения пользовательских объектов. Блок возвращает NSComparisonResultзначение для обозначения порядка двух объектов. Поэтому для сортировки всего массива NSComparatorиспользуется следующий способ.

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

Сортировка с использованием NSSortDescriptor
Предположим, в качестве примера, что у нас есть массив, содержащий экземпляры пользовательского класса, у Employee есть атрибуты имя, фамилия и возраст. В следующем примере показано, как создать 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 / как к своего рода-NSArray-с-пользовательских-объектов /

Аамир
источник
1

Протоколы и функциональное программирование 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)
Джеймс Рочабрун
источник
1

В моем случае я использую «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
Эмре Гюрсес
источник
1

Вы должны создать 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)
Парт Баро
источник
1

Используйте как это для вложенных объектов,

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

lastRoute - это один объект, и этот объект содержит объект to, этот объект содержит строковые значения lastname.

Сурешкумар Линганатан
источник
0

Сортировать массив в Swift


Для 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>

Сайед Камар Аббас
источник
0

Swift версия: 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
источник
0
  let sortedUsers = users.sorted {
    $0.firstName < $1.firstName
 }
manishkumar
источник
Речь идет о NSMutableArray, а не о коллекции Arrays в Swift
Рикардо
-2
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(@"===============================");
Siddhesh Bondre
источник