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


11 Answers

راجع أسلوب طريقة sortUsingFunction:context:

ستحتاج إلى إعداد وظيفة مقارنة تأخذ شيئين (من نوع Person ، بما أنك تقارن بين شخصين) ومعلمة سياق .

والكائنات هما مجرد أمثلة Person . الكائن الثالث عبارة عن سلسلة ، على سبيل المثال @ "birthdate".

ترجع هذه الدالة NSComparisonResult : تقوم بإرجاع NSOrderedAscending إذا كان PersonA.birthDate < PersonB.birthDate . سيعود NSOrderedDescending حالة PersonA.birthDate > PersonB.birthDate . وأخيرًا ، سيعود NSOrderedSame إذا كان PersonA.birthDate == PersonB.birthDate .

هذا هو pseudocode الخام. ستحتاج إلى توضيح ما يعنيه لتاريخ واحد ليكون "أقل" ، "أكثر" أو "مساوٍ" لتاريخ آخر (مثل مقارنة الثواني - منذ - حقبة إلخ.):

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

ربما يمكن أن يسرع هذا الأمر قليلاً ، إذا قمت بذلك كثيرًا.

Question

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

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

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

في Java ، أجعل الكائن تنفيذًا قابل للمقارنة ، أو استخدم Collections.sort مع مقارنة مخصصة مضمنة ... كيف تقوم بذلك على الأرض في Objective-C؟




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




يمكنك فرز مجموعة من الكائنات المخصصة باستخدام الفرز السريع. يرجى الاطلاع على المثال أدناه باستخدام 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)")
    }



أنا فعلت فرز على مستوى متعدد على أساس متطلبات مخصصة.

// فرز القيم

    [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




بدءًا من 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];

ملحوظة: سيتم تجهيز المصفوفة "المصنفة" تلقائيًا.




يجب عليك إنشاء 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)



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

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



في حالتي ، أستخدم "sortedArrayUsing COMparator" لتصنيف مصفوفة. انظر إلى الرمز أدناه.

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



-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}



تحتاج كائنات " Person الخاصة بك إلى تطبيق طريقة ، قل compare: التي تأخذ كائن Person آخر ، وإرجاع NSComparisonResult وفقًا للعلاقة بين الكائنات 2.

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

هناك طرق أخرى ، ولكن بقدر ما أعرف لا يوجد كاكاو - equiv من واجهة قابلة Comparable . استخدام sortedArrayUsingSelector: هو على الأرجح الطريقة الأكثر sortedArrayUsingSelector: للقيام بذلك.




إن بروتوكولات Swift والبرمجة الوظيفية تجعل من السهل عليك فقط جعل صفك مطابقاً للبروتوكول المقارن ، وتنفيذ الطرق التي يتطلبها البروتوكول ثم استخدام الدالة المرتبة عالية الجودة (بواسطة:) لإنشاء مصفوفة مرتبة بدون الحاجة إلى استخدام صفائف قابلة للتغيير من جانب الطريق.

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)



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

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



Related