سؤال

انا لدي NSArray وأود أن إنشاء جديد NSArray مع كائنات من المصفوفة الأصلية التي تستوفي معايير معينة.يتم تحديد المعايير بواسطة دالة تُرجع a BOOL.

يمكنني إنشاء NSMutableArray, ، قم بالتكرار عبر المصفوفة المصدر ونسخ الكائنات التي تقبلها وظيفة التصفية ثم قم بإنشاء نسخة غير قابلة للتغيير منها.

هل هناك طريقة أفضل؟

هل كانت مفيدة؟

المحلول

NSArray و NSMutableArray توفير طرق لتصفية محتويات المصفوفة. NSArray يوفر filteredArrayUsingPredicate: الذي يُرجع مصفوفة جديدة تحتوي على كائنات في جهاز الاستقبال تتطابق مع المسند المحدد. NSMutableArray يضيف مرشح باستخدام المسند: الذي يقيم محتوى المتلقي مقابل المسند المحدد ويترك فقط الكائنات المطابقة.يتم توضيح هذه الطرق في المثال التالي.

NSMutableArray *array =
    [NSMutableArray arrayWithObjects:@"Bill", @"Ben", @"Chris", @"Melissa", nil];

NSPredicate *bPredicate =
    [NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"];
NSArray *beginWithB =
    [array filteredArrayUsingPredicate:bPredicate];
// beginWithB contains { @"Bill", @"Ben" }.

NSPredicate *sPredicate =
    [NSPredicate predicateWithFormat:@"SELF contains[c] 's'"];
[array filteredArrayUsingPredicate:sPredicate];
// array now contains { @"Chris", @"Melissa" }

نصائح أخرى

هناك الكثير من الطرق للقيام بذلك، ولكن من المؤكد أن أفضلها هو الاستخدام [NSPredicate predicateWithBlock:]:

NSArray *filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
    return [object shouldIKeepYou];  // Return YES for each object you want in filteredArray.
}]];

أعتقد أن هذا موجز بقدر ما يبدو.


سويفت:

لأولئك الذين يعملون مع NSArrayفي Swift، قد تفضل هذا أكثر من ذلك نسخة موجزة:

nsArray = nsArray.filter { $0.shouldIKeepYou() }

filter هو مجرد وسيلة على Array (NSArray تم ربطه ضمنيًا بـ Swift Array).يستغرق حجة واحدة:إغلاق يأخذ كائنًا واحدًا في المصفوفة ويعيد ملفًا Bool.في إغلاقك، فقط ارجع true لأية كائنات تريدها في المصفوفة التي تمت تصفيتها.

إذا كان نظامك OS X 10.6/iOS 4.0 أو أحدث، فمن الأفضل أن تستخدم الكتل بدلاً من NSPredicate.يرى -[NSArray indexesOfObjectsPassingTest:] أو اكتب الفئة الخاصة بك لإضافة مفيد -select: أو -filter: طريقة (مثال).

هل تريد أن يقوم شخص آخر بكتابة هذه الفئة واختبارها وما إلى ذلك؟الدفع BlockKit (مستندات المصفوفة).و ها هم كثير يمكن العثور على المزيد من الأمثلة من خلال البحث عنها على سبيل المثال. "اختيار فئة كتلة nsarray".

بناءً على إجابة كلاي بريدجز، إليك مثال على التصفية باستخدام الكتل (التغيير yourArray إلى اسم متغير الصفيف الخاص بك و testFunc إلى اسم وظيفة الاختبار الخاصة بك):

yourArray = [yourArray objectsAtIndexes:[yourArray indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
    return [self testFunc:obj];
}]];

على افتراض أن الكائنات الخاصة بك كلها من نفس النوع، يمكنك إضافة طريقة كفئة من فئتها الأساسية التي تستدعي الوظيفة التي تستخدمها لمعاييرك.ثم قم بإنشاء كائن NSPredicate الذي يشير إلى تلك الطريقة.

في بعض الفئات، حدد طريقتك التي تستخدم وظيفتك

@implementation BaseClass (SomeCategory)
- (BOOL)myMethod {
    return someComparisonFunction(self, whatever);
}
@end

ثم أينما ستقوم بالتصفية:

- (NSArray *)myFilteredObjects {
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMethod = TRUE"];
    return [myArray filteredArrayUsingPredicate:pred];
}

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

NSPredicate هي طريقة nextstep لإنشاء شرط لتصفية مجموعة (NSArray, NSSet, NSDictionary).

على سبيل المثال النظر في صفيفين arr و filteredarr:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];

filteredarr = [NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

من المؤكد أن المرشح سيحتوي على العناصر التي تحتوي على الحرف c وحده.

لتسهيل تذكر أولئك الذين لديهم خلفية SQL صغيرة

*--select * from tbl where column1 like '%a%'--*

1) حدد * من tbl --> جمع

2) العمود 1 مثل "%a%" --> NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];

3) حدد * من tbl حيث العمود 1 مثل "%a%" -->

[NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

آمل أن يساعد هذا

NSArray+X.h

@interface NSArray (X)
/**
 *  @return new NSArray with objects, that passing test block
 */
- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate;
@end

NSArray+X.m

@implementation NSArray (X)

- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
{
    return [self objectsAtIndexes:[self indexesOfObjectsPassingTest:predicate]];
}

@end

يمكنك تنزيل هذه الفئة هنا

الخروج من هذه المكتبة

https://github.com/BadChoice/Collection

لأنه يأتي مع الكثير من وظائف المصفوفة السهلة لعدم كتابة حلقة مرة أخرى

لذلك يمكنك فقط القيام بما يلي:

NSArray* youngHeroes = [self.heroes filter:^BOOL(Hero *object) {
    return object.age.intValue < 20;
}];

أو

NSArray* oldHeroes = [self.heroes reject:^BOOL(Hero *object) {
    return object.age.intValue < 20;
}];

الطريقة الأفضل والسهلة هي إنشاء هذه الطريقة وتمرير المصفوفة والقيمة:

- (NSArray *) filter:(NSArray *)array where:(NSString *)key is:(id)value{
    NSMutableArray *temArr=[[NSMutableArray alloc] init];
    for(NSDictionary *dic in self)
        if([dic[key] isEqual:value])
            [temArr addObject:dic];
    return temArr;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top