ios كيف يمكنني فرز NSMutableArray مع كائنات مخصصة في ذلك؟




objective-c sorting (17)

ترتيب المصفوفة في سويفت

ل Swifty Person أدناه هو تقنية نظيفة للغاية لتحقيق هدف أعلاه على الصعيد العالمي. يتيح الحصول على فئة مخصصة من User والتي لها بعض السمات.

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

الآن لدينا مجموعة نحتاج إلى createdDate على أساس 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)

لا يمكن الوصول إلى الطريقة المذكورة أعلاه إلا إذا كان Array من النوع [User] || Array<User>

https://code.i-harness.com

ما أريد فعله يبدو بسيطًا جدًا ، ولكن لا يمكنني العثور على أي إجابات على الويب. لدي NSMutableArray من الكائنات ، ودعونا نقول أنها كائنات "شخص". أريد فرز NSMutableArray بواسطة Person.birthDate وهو NSDate.

أعتقد أن لها علاقة بهذه الطريقة:

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

في Java ، أجعل الكائن تنفيذًا قابل للمقارنة ، أو استخدم 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(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

أداء

سيكون -compare: والأساليب المستندة إلى كتلة أسرع قليلاً بشكل عام ، من استخدام NSSortDescriptor لأن الأخير يعتمد على KVC. تتمثل الميزة الأساسية لطريقة NSSortDescriptor أنها توفر طريقة لتحديد ترتيب الفرز باستخدام البيانات ، بدلاً من التعليمة البرمجية ، مما يجعل من السهل إعداد العناصر بحيث يمكن للمستخدمين فرز NSTableView بالنقر فوق صف الرأس.


أنا فعلت هذا في iOS 4 باستخدام كتلة. كان عليه أن يلقي عناصر صفيفي من معرف إلى نوع الفصل. في هذه الحالة ، كانت فئة تسمى درجة مع خاصية تسمى النقاط.

كما تحتاج إلى تحديد ما يجب فعله إذا لم تكن عناصر الصفيف الخاص بك هي النوع الصحيح ، لهذا المثال عدت للتو 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;

ملاحظة: هذا هو فرز بترتيب تنازلي.


إذا كنت تقوم فقط بفرز مصفوفة من 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]];

أميل إلى تفضيل عبارات بسيطة والكثير من المتغيرات المؤقتة لأن التعليمة البرمجية أسهل في القراءة ، وأسهل في التصحيح. يقوم المترجم بتحسين المتغيرات المؤقتة على أي حال ، لذلك لا توجد ميزة للإصدار المتكامل في سطر واحد.


بدءًا من 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 وفقًا للعلاقة بين الكائنات 2.

ثم يمكنك استدعاء sortedArrayUsingSelector: مع @selector(compare:) ويجب أن يتم ذلك.

هناك طرق أخرى ، ولكن بقدر ما أعرف لا يوجد كاكاو - equiv من واجهة قابلة Comparable . استخدام sortedArrayUsingSelector: هو على الأرجح الطريقة الأكثر 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 بسيط جدا:

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

لقد استخدمت 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];

لقد جربت كل شيء ، لكن هذا عمل بالنسبة لي. في الفصل الدراسي لديّ فصل آخر اسمه " crimeScene " ، وأريد الفرز حسب خاصية " crimeScene ".

هذا يعمل مثل السحر:

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

من أجل NSMutableArray ، استخدم الأسلوب sortUsingSelector . يقوم بترتيب مكانه ، بدون إنشاء مثيل جديد.


هناك خطوة مفقودة في إجابة جورج شولي الثانية ، لكنها تعمل بشكل جيد في ذلك الوقت.

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

يمكنك استخدام الطريقة العامة التالية لغرضك. يجب أن تحل مشكلتك.

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

يمكنك فرز مجموعة من الكائنات المخصصة باستخدام الفرز السريع. يرجى الاطلاع على المثال أدناه باستخدام Swift 4

func sortArrayOfPersonInAscendingOrder() {
        if self.arrSortingPersons != nil, self.arrSortingPersons.count > 0 {
            self.arrSortingPersons.sort(by: { (person1, person2) -> Bool in
                return person1.birthDate < person2.birthDate
            })
        }

        print("Sorted Array In Ascending Order:\n\(self.arrSortingPersons)")
    }

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