简体   繁体   中英

NSArray of Objects sorting with Custom Logic

I have NSSArray having Custom Objects, To sort the Custom Object with Custom logic

Custom object having two property:
@property (nonatomic, strong) NSString *objectName;
@property (nonatomic, assign) BOOL isValidName;

if isValidName property is false, Then the custom object should be last sorting order. for the objects isValidName property is true, Then it should be sort with property objectName in ascending.

I can do with for loop by finding objects having property isValidName false then remove the objects from the array and then sort the array after that I can add the objects which are having property isValidName false. I don't want to do that.

I want that something like below option, But it is not working. Please help in regard

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSArray *sortedTopics = [obj sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
             if (obj1.isValidName) {  
                return NSOrderedAscending;
            }
            return [obj1.objectName compare: obj2.objectName options:NSCaseInsensitiveSearch];
        }];
        obj = sortedTopics;

    }];

I dont really recreated the stuff you did, but i hope this would work for you: arr should be NSMutableArray

NSSortDescriptor *validSort = [[NSSortDescriptor alloc] initWithKey:@"isValidName" ascending:NO];
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"objectName" ascending:YES];

[arr sortUsingDescriptors:[NSArray validSort, nameSort, nil]];

So if your object.isValidName = false it will push to after the one have it true and also sort by name

Try using NSPredicate

  NSMutableArray *arrFinalSortedArray = [NSMutableArray new];

NSArray *yourObjectArray = @[@{@"isValidName":@"YES" ,@"objectName":@"ABC"},@{@"isValidName":@"NO",@"objectName":@"EFG"},@{@"isValidName":@"YES",@"objectName":@"BCD"},@{@"isValidName":@"YES",@"objectName":@"CDE"},@{@"isValidName":@"NO",@"objectName":@"DEF"}];

    // filter for NO flag
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isValidName ==[c] %@", @"NO"];
    NSArray *NOContainerArray = [yourObjectArray  filteredArrayUsingPredicate:predicate];
    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"objectName" ascending:YES];
    NOContainerArray = [NOContainerArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];

    // filter for NO flag
    predicate = [NSPredicate predicateWithFormat:@"isValidName ==[c] %@", @"YES"];
    NSArray *YESContainerArray = [yourObjectArray  filteredArrayUsingPredicate:predicate];
    descriptor = [NSSortDescriptor sortDescriptorWithKey:@"objectName" ascending:YES];
    YESContainerArray = [YESContainerArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];

    // add to all YES and NO array into the final array which is the your result
    [arrFinalSortedArray addObjectsFromArray:YESContainerArray];
    [arrFinalSortedArray addObjectsFromArray:NOContainerArray];
    NSLog(@"%@",arrFinalSortedArray);

I think you almost had it, but you shouldn't be using enumerateObjectsUsingBlock . Instead use sortedArrayUsingComparator and assign the result to a new array:

NSArray *sortedTopics = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
    if (!obj1.isValidName)
        return NSOrderedDescending;
    return [obj1.objectName compare: obj2.objectName options:NSCaseInsensitiveSearch];
}];

If you have an NSMutableArray you can call sortUsingComparator: on it instead and avoid creating a new array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM