Sort NSArray custom objects by another NSArray custom objects

て烟熏妆下的殇ゞ 提交于 2019-12-12 03:50:03

问题


I have 2 different NSArray with custom objects as follows,

Item *item1 = [[Items alloc] init];
item1.number = @"1";
item1.serailNumber = @"S01";

Item *item2 = [[Items alloc] init];
item2.number = @"2";
item2.serailNumber = @"S02";

Item *item3 = [[Items alloc] init];
item3.number = @"3";
item3.serailNumber = @"S03";

Item *item4 = [[Items alloc] init];
item4.number = @"4";
item4.serailNumber = @"S04";

Item *item5 = [[Items alloc] init];
item5.number = @"5";
item5.serailNumber = @"S05";

NSArray *items = @[item1, item2, item3, item4, item5]; 

NSArray *specList = @[@{"number" : @"002", @"serialNumber" : @"S02"},
                     @{"number" : @"004", @"serialNumber" : @"S04"},
                     @{"number" : @"003", @"serialNumber" : @"S03"}];

Now I want to sort my items array based on specList array by comparing "number" property.

Now my expected items list is,

@[item2, item4, item3, item1, item5]

I have gone through several samples as listed below but I couldn't figure out how to compare with custom objects. Any help would be appreciated, Thanks in advance.

Sample 1 Sample 2


回答1:


This should do the trick:

NSArray *sorted = [items sortedArrayUsingComparator:^NSComparisonResult(Item *item1, Item *item2) {
    NSInteger indexForItemEquivalent1InSpecList = [self indexForItem:item1 inList:specList];
    NSInteger indexForItemEquivalent2InSpecList = [self indexForItem:item2 inList:specList];
    return [@(indexForItemEquivalent1InSpecList) compare:@(indexForItemEquivalent2InSpecList)];
}];

NSLog(@"Sorted: %@", sorted);

With:

-(NSInteger)indexForItem:(Item *)item inList:(NSArray *)list
{
    for (NSInteger i = 0; i < [list count]; i++)
    {
        if ([list[i][@"number"] integerValue] == [[item number] integerValue])
        {
            return i;
        }
    }
    return NSIntegerMax; //If not found, we put it at the end of the list
}

Output:

Sorted: (
    "<Item 0x146678f0> number: 2 serial: S02",
    "<Item 0x14667e10> number: 4 serial: S04",
    "<Item 0x14667900> number: 3 serial: S03",
    "<Item 0x14654200> number: 1 serial: S01",
    "<Item 0x14667e20> number: 5 serial: S05"
)

I override -description to make log clearer:

-(NSString *)description
{
    return [NSString stringWithFormat:@"<%@ %p> number: %@ serial: %@", [self class], self, _number, _serailNumber];
}

In other words:
You have to find the index of the corresponding Item object inside specList (see indexForItem:inList:). I used integerValue because you are using @"002" and @"2", which aren't equal strings.
Then in the NSComparator you compare the two indexes.

For item1 and item5 which are at the end, I let them as if. There is no guarantee of their order since they are not present in specList. If you want to put them in "ascending" order, you have to do instead:

NSInteger indexForItem1InSpecList = [self indexForItem:item1 inList:specList];
NSInteger indexForItem2InSpecList = [self indexForItem:item2 inList:specList];
if (indexForItem1InSpecList == NSIntegerMax && indexForItem2InSpecList == NSIntegerMax)
{
    return [@([[item1 number] integerValue]) compare:@([[item2 number] integerValue])];
}
else
{
    return [@(indexForItem1InSpecList) compare:@(indexForItem2InSpecList)];
}



回答2:


Here is an example of sorting second array referring to the first one:

NSArray *users = @[@"Dave",@"Mike",@"Joe",@"Jason",@"Kevin"];
NSArray *iqs = @[@110,@145,@75,@122,@130];

NSMutableArray *array = [NSMutableArray array];
for (int idx = 0;idx<[users count];idx++) {
    NSDictionary *dict = @{@"Name": users[idx],@"IQ":iqs[idx]};
    [array addObject:dict];
}

NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"IQ" ascending:NO];
[array sortUsingDescriptors:@[descriptor]];


来源:https://stackoverflow.com/questions/38768463/sort-nsarray-custom-objects-by-another-nsarray-custom-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!