Làm cách nào để sắp xếp NSMutableArray với các đối tượng tùy chỉnh trong đó?


1268

Những gì tôi muốn làm có vẻ khá đơn giản, nhưng tôi không thể tìm thấy bất kỳ câu trả lời nào trên web. Tôi có một NSMutableArrayđối tượng và giả sử chúng là đối tượng 'Người'. Tôi muốn sắp xếp NSMutableArraytheo Person.birthDate là một NSDate.

Tôi nghĩ rằng nó có một cái gì đó để làm với phương pháp này:

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

Trong Java, tôi sẽ làm cho đối tượng của mình triển khai Có thể so sánh hoặc sử dụng Collections.sort với một trình so sánh tùy chỉnh nội tuyến ... làm thế nào để bạn làm điều này trong Objective-C?

Câu trả lời:


2299

Phương pháp so sánh

Hoặc bạn thực hiện một phương thức so sánh cho đối tượng của mình:

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

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

NSSortDescriptor (tốt hơn)

hoặc thường tốt hơn:

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

Bạn có thể dễ dàng sắp xếp theo nhiều khóa bằng cách thêm nhiều hơn một vào mảng. Sử dụng phương pháp so sánh tùy chỉnh là có thể là tốt. Có một cái nhìn vào các tài liệu .

Khối (sáng bóng!)

Ngoài ra còn có khả năng sắp xếp với một khối kể từ Mac OS X 10.6 và 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];
}];

Hiệu suất

Các -compare:phương thức dựa trên khối và khối sẽ nhanh hơn một chút, nói chung, hơn là sử dụng NSSortDescriptornhư phương pháp sau dựa trên KVC. Ưu điểm chính của NSSortDescriptorphương thức là nó cung cấp một cách để xác định thứ tự sắp xếp của bạn bằng cách sử dụng dữ liệu, thay vì mã, giúp dễ dàng thiết lập mọi thứ để người dùng có thể sắp xếp NSTableViewbằng cách nhấp vào hàng tiêu đề.


66
Ví dụ đầu tiên có một lỗi: Bạn so sánh biến đối tượng birthdayDate trong một đối tượng với chính đối tượng đó, chứ không phải là biến birthdayDate của nó.
Martin Gjaldbaek

90
@Martin: Cảm ơn! Thật buồn cười là không ai khác nhận thấy trước khi tôi nhận được 75 lượt upvote cho nó.
Georg Schölly

76
Vì đây là câu trả lời được chấp nhận và do đó có lẽ được hầu hết người dùng xem là dứt khoát, nên có thể hữu ích khi thêm ví dụ thứ 3, dựa trên khối để người dùng cũng biết rằng nó tồn tại.
jpswain

6
@ cam80: Tôi đã thử nó. Tôi không sở hữu máy Mac nữa, vì vậy sẽ rất tuyệt nếu bạn có thể xem mã.
Georg Schölly

11
Nếu bạn có một NSMutableArraytôi thích sử dụng các phương thức sortUsingDescriptors, sortUsingFunctionhoặc sortUsingSelector. Theo như mảng có thể thay đổi, tôi thường không cần một bản sao được sắp xếp.
Stephan

109

Xem NSMutableArrayphương phápsortUsingFunction:context:

Bạn sẽ cần thiết lập một hàm so sánh có hai đối tượng (cùng loại Person, vì bạn đang so sánh hai Personđối tượng) và một tham số ngữ cảnh .

Hai đối tượng chỉ là trường hợp của Person. Đối tượng thứ ba là một chuỗi, ví dụ @ "birthdayDate".

Hàm này trả về một NSComparisonResult: Nó trả về NSOrderedAscendingnếu PersonA.birthDate< PersonB.birthDate. Nó sẽ trở lại NSOrderedDescendingnếu PersonA.birthDate> PersonB.birthDate. Cuối cùng, nó sẽ trở lại NSOrderedSamenếu PersonA.birthDate== PersonB.birthDate.

Đây là mã giả thô; bạn sẽ cần xác định ý nghĩa của một ngày là "ít hơn", "nhiều hơn" hoặc "bằng" với một ngày khác (chẳng hạn như so sánh giây-kể từ kỷ nguyên, v.v.):

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

Nếu bạn muốn một cái gì đó nhỏ gọn hơn, bạn có thể sử dụng các toán tử ternary:

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

Nội tuyến có thể tăng tốc điều này lên một chút, nếu bạn làm điều này rất nhiều.


9
Sử dụng sortUsingFunction: bối cảnh: có lẽ là cách c-ish nhất và chắc chắn là cách khó đọc nhất.
Georg Schölly

12
Không có gì thực sự sai với nó, nhưng tôi nghĩ bây giờ có nhiều lựa chọn thay thế tốt hơn nhiều.
Georg Schölly

6
Có lẽ, nhưng tôi không nghĩ nó sẽ dễ đọc hơn đối với ai đó từ nền Java, người có thể đang tìm kiếm thứ gì đó tương tự như lớp So sánh trừu tượng của Java, thực hiện so sánh (Loại obj1, Loại obj2).
Alex Reynold

5
Tôi có cảm giác một vài bạn đang tìm kiếm bất kỳ lý do nào để chỉ trích câu trả lời hoàn toàn tốt đẹp này, ngay cả khi lời chỉ trích đó có rất ít thành tích kỹ thuật. Kỳ dị.
Alex Reynold

1
@Yar: Hoặc bạn có thể sử dụng giải pháp tôi đã cung cấp trong đoạn đầu tiên hoặc bạn sử dụng nhiều mô tả sắp xếp. sortArrayUsingDescriptors: lấy một mảng các mô tả sắp xếp làm đối số.
Georg Schölly

62

Tôi đã làm điều này trong iOS 4 bằng cách sử dụng một khối. Phải truyền các phần tử của mảng từ id sang loại lớp của tôi. Trong trường hợp này, đó là một lớp được gọi là Điểm với một thuộc tính được gọi là điểm.

Ngoài ra, bạn cần phải quyết định phải làm gì nếu các phần tử của mảng không đúng loại, ví dụ này tôi vừa trả về NSOrderedSame, tuy nhiên trong mã của tôi, tôi mặc dù là một ngoại lệ.

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: Đây là sắp xếp theo thứ tự giảm dần.


6
Bạn thực sự không cần các phôi "(Điểm *)" trong đó, bạn chỉ có thể thực hiện "Điểm * s1 = obj1;" bởi vì id sẽ vui vẻ truyền tới mọi thứ mà không cần cảnh báo từ trình biên dịch :-)
jpswain

phải cam80 downcastingkhông yêu cầu diễn viên trước biến yếu.
thesummersign

Bạn nên sắp xếp nil vs not-nil lên trên cùng hoặc dưới cùng một cách nhất quán, vì vậy lợi nhuận cuối cùng mặc định có thể làreturn ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending))
Scott Corscadden

heh Chris, tôi đã thử mã này, tôi làm mới trong chương trình của mình .. lần đầu tiên tôi thực hiện đúng công việc, có đầu ra thứ tự giảm dần .. nhưng khi tôi làm mới. (thực thi cùng mã với cùng dữ liệu) thì nó đã thay đổi thứ tự, nó không giảm dần .. Giả sử tôi hv 4 đối tượng trong mảng của tôi, 3 hv cùng một dữ liệu, 1 là khác nhau.
Nikesh K

Nếu bạn thực sự mong đợi các đối tượng không thuộc lớp "Điểm", bạn cần sắp xếp chúng cẩn thận hơn một chút. Nếu không, bạn có một tình huống khác == points1 <points2 == khác không phù hợp và có thể dẫn đến rắc rối. Bạn có thể trả về một giá trị ngụ ý sắp xếp các đối tượng Điểm trước tất cả các đối tượng khác và tất cả các đối tượng khác sắp xếp bằng nhau.
gnasher729

29

Bắt đầu trong iOS 4, bạn cũng có thể sử dụng các khối để sắp xếp.

Trong ví dụ cụ thể này, tôi giả sử rằng các đối tượng trong mảng của bạn có phương thức 'vị trí', trả về một 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];

Lưu ý: mảng "đã sắp xếp" sẽ được tự động phát hành.


26

Tôi đã thử tất cả, nhưng điều này làm việc cho tôi. Trong một lớp tôi có một lớp khác có tên " crimeScene" và muốn sắp xếp theo một thuộc tính của " crimeScene".

Công việc này như một cái duyên vậy:

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

21

Có một bước còn thiếu trong câu trả lời thứ hai của Georg Schölly , nhưng sau đó nó hoạt động tốt.

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

// đã thêm 's' vì thời gian bị lãng phí khi tôi sao chép và dán và nó đã thất bại nếu không có 's' trong sortArrayUsingDescriptors


Cuộc gọi phương thức thực sự là "sortArrayUsingDescriptors:", với một 's' ở cuối.
CIFilter

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

Cảm ơn, nó hoạt động tốt ...


17

Các Personđối tượng của bạn cần thực hiện một phương thức, giả sử compare:lấy một Personđối tượng khác và trả về NSComparisonResulttheo mối quan hệ giữa 2 đối tượng.

Sau đó, bạn sẽ gọi sortedArrayUsingSelector:với@selector(compare:) và nó nên được thực hiện.

Có nhiều cách khác, nhưng theo tôi biết thì không có Cacao-Equiv của Comparablegiao diện. Sử dụng sortedArrayUsingSelector:có lẽ là cách dễ dàng nhất để làm điều đó.


9

Các khối iOS 4 sẽ giúp bạn tiết kiệm :)

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 một chút mô tả


8

Đối với NSMutableArray, sử dụng sortUsingSelectorphương pháp. Nó sắp xếp nó - nơi, mà không tạo ra một thể hiện mới.


Chỉ là một bản cập nhật: Tôi cũng đang tìm kiếm thứ gì đó sắp xếp mảng có thể thay đổi, hiện có các phương thức tương đương "sortUsing" cho tất cả các phương thức "sortArrayUsing" kể từ iOS 7. Chẳng hạn như sortUsingComparator:.
jmathew

7

Bạn có thể sử dụng phương pháp chung sau đây cho mục đích của bạn. Nó sẽ giải quyết vấn đề của bạn.

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

Nếu bạn chỉ sắp xếp một mảng NSNumbers, bạn có thể sắp xếp chúng với 1 cuộc gọi:

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

Điều đó hoạt động vì các đối tượng trong mảng ( NSNumberđối tượng) thực hiện phương thức so sánh. Bạn có thể làm điều tương tự cho NSStringcác đối tượng hoặc thậm chí cho một mảng các đối tượng dữ liệu tùy chỉnh thực hiện phương thức so sánh.

Dưới đây là một số mã ví dụ sử dụng các khối so sánh. Nó sắp xếp một loạt các từ điển trong đó mỗi từ điển bao gồm một số trong một khóa "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;
 }];

Đoạn mã trên trải qua công việc lấy một giá trị nguyên cho mỗi khóa sắp xếp và so sánh chúng, như một minh họa về cách thực hiện. Vì NSNumbercác đối tượng thực hiện một phương thức so sánh, nó có thể được viết lại đơn giản hơn nhiều:

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

hoặc phần thân của bộ so sánh thậm chí có thể được chưng cất xuống 1 dòng:

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

Tôi có xu hướng thích các câu lệnh đơn giản và nhiều biến tạm thời vì mã dễ đọc hơn và dễ gỡ lỗi hơn. Trình biên dịch tối ưu hóa đi các biến tạm thời, vì vậy không có lợi thế cho phiên bản tất cả trong một dòng.


5

Tôi đã tạo ra một thư viện nhỏ các phương thức thể loại, được gọi là Linq to ObjectiveC , giúp cho việc này trở nên dễ dàng hơn. Sử dụng phương thức sắp xếp với bộ chọn khóa, bạn có thể sắp xếp theo birthDatenhư sau:

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

Bạn nên gọi nó là " LINQ to Objective-C ".
Peter Mortensen

5

Tôi chỉ thực hiện sắp xếp đa cấp dựa trên yêu cầu tùy chỉnh.

// sắp xếp các giá trị

    [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


5

Tôi đã sử dụng sortUsingFunction :: trong một số dự án của mình:

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

5

Bạn sử dụng NSSortDescriptor để sắp xếp NSMutableArray với các đối tượng tùy chỉnh

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

Tại sao phải vượt qua trong một mảng có thể thay đổi, khi một mảng mới được trả về. Tại sao để tạo ra một trình bao bọc ở tất cả?
vikingosegundo

3

Sắp xếp NSMutableArrayrất đơn giản:

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

Sắp xếp bằng NSComparator

Nếu chúng ta muốn sắp xếp các đối tượng tùy chỉnh, chúng ta cần cung cấp NSComparator, được sử dụng để so sánh các đối tượng tùy chỉnh. Khối trả về một NSComparisonResultgiá trị để biểu thị thứ tự của hai đối tượng. Vì vậy, để sắp xếp toàn bộ mảng NSComparatorđược sử dụng theo cách sau.

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

Sắp xếp bằng NSSortDescriptor
Hãy giả sử, ví dụ, chúng ta có một mảng chứa các thể hiện của một lớp tùy chỉnh, Nhân viên có các thuộc tính tên, họ và tuổi. Ví dụ sau minh họa cách tạo NSSortDescriptor có thể được sử dụng để sắp xếp nội dung mảng theo thứ tự tăng dần theo khóa tuổi.

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

Sắp xếp bằng So sánh tùy chỉnh
Tên là các chuỗi và khi bạn sắp xếp các chuỗi để trình bày cho người dùng, bạn phải luôn sử dụng so sánh được bản địa hóa. Thường thì bạn cũng muốn thực hiện một trường hợp so sánh không nhạy cảm. Dưới đây là một ví dụ với (localizedSt ChuẩnCompare :) để đặt hàng theo tên và họ.

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

Để tham khảo và thảo luận chi tiết, vui lòng tham khảo: https://developer.apple.com/l Library / ios / documentation / Coloa / Contualual / CortDescriptors / Articles / Treating.html
http://www.ios-blog.co.uk/tutorials / object-c / how-to-sort-nsarray-with-custom-object /


1

Các giao thức và lập trình chức năng của Swift giúp bạn dễ dàng tạo lớp phù hợp với giao thức so sánh, thực hiện các phương thức theo yêu cầu của giao thức và sau đó sử dụng hàm bậc cao được sắp xếp (by :) để tạo một mảng được sắp xếp mà không cần sử dụng bằng cách biến đổi mảng bằng cách này.

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

Trong trường hợp của tôi, tôi sử dụng "sortArrayUsingComparator" để sắp xếp một mảng. Nhìn vào đoạn mã dưới đây.

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

Ngoài ra đối tượng của tôi là,

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

1

Bạn phải tạo sortDescriptor và sau đó bạn có thể sắp xếp nsmutablearray bằng cách sử dụng sortDescriptor như bên dưới.

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

1

Sử dụng như thế này cho các đối tượng lồng nhau,

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

lastRoute là một đối tượng và đối tượng đó giữ đối tượng to, đối tượng đó giữ các giá trị chuỗi họ.


0

Sắp xếp mảng trong Swift


Đối với SwiftyNgười dưới đây là một kỹ thuật rất sạch sẽ để đạt được mục tiêu trên cho toàn cầu. Cho phép có một lớp tùy chỉnh ví dụ trong Userđó có một số thuộc tính.

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

Bây giờ chúng ta có một mảng mà chúng ta cần sắp xếp trên cơ sở createdDatetăng dần và / hoặc giảm dần. Vì vậy, hãy thêm một chức năng để so sánh ngày.

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

Bây giờ cho phép có một extensionsố Arraycho User. Nói một cách đơn giản, chỉ cho phép thêm một số phương thức cho các Array chỉ có Usercác đối tượng trong đó.

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

Cách sử dụng cho thứ tự tăng dần

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Cách sử dụng cho thứ tự giảm dần

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Cách sử dụng cho cùng một đơn hàng

let sortedArray = someArray.sortUserByDate(.orderedSame)

Phương thức trên extensionsẽ chỉ có thể truy cập được nếu Arraythuộc loại [User]| |Array<User>


0

Phiên bản Swift: 5.1

Nếu bạn có một cấu trúc hoặc lớp tùy chỉnh và muốn sắp xếp chúng một cách tùy ý, bạn nên gọi sort () bằng cách sử dụng bao đóng dấu theo thứ tự sắp xếp trên một trường bạn chỉ định. Dưới đây là một ví dụ sử dụng một loạt các cấu trúc tùy chỉnh sắp xếp trên một thuộc tính cụ thể:

    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
    }

Nếu bạn muốn trả về một mảng đã sắp xếp thay vì sắp xếp nó tại chỗ, hãy sử dụng sort () như thế này:

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

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

Câu hỏi là về NSMutableArray, không phải về bộ sưu tập Mảng trong Swift
Ricardo

-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(@"===============================");
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.