通过第二维对NSArray进行排序 - Objective-C

时间:2017-11-10 18:01:18

标签: ios objective-c sorting nsarray

历史上,此排序工厂已能够按一个维度对一组Invoice Item对象进行排序。各种排序维度作为SortItem对象的属性存储在枚举“状态”中。这是工作实施。

+(NSArray *)SortInvoiceItems:(NSArray *)items forSort:(SortItem*)sortItem forSecondarySort:(SortItem*)secondarySortItem {
    NSArray * primary = [items sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
        InvoiceItems *iiA = (InvoiceItems *)a;
        InvoiceItems *iiB = (InvoiceItems *)b;
        switch(sortItem.state) {
            case DateAscending:
            case DateDescending: {
                return (sortItem.state == DateAscending) ? [iiA.transactionDate compare:iiB.transactionDate] : [iiB.transactionDate compare:iiA.transactionDate];
            }
            case SumDescending:
            case SumAscending: {
                return (sortItem.state == SumAscending) ? [iiA.netInvoiceAmount compare:iiB.netInvoiceAmount] : [iiB.netInvoiceAmount compare:iiA.netInvoiceAmount];
            }
            case UnitPriceDescending:
            case UnitPriceAscending: {
                return (sortItem.state == UnitPriceAscending) ? [iiA.uomNetAmt compare:iiB.uomNetAmt] : [iiB.uomNetAmt compare:iiA.uomNetAmt];
            }
            default:
                return 0;
        }
    }];

    return primary;
}

你会注意到我已经在未使用的方法签名中添加了一个secondarySort参数。我的目标是允许按此辅助维度进行排序,通过此辅助维度对主要维度具有相同值的“发票项目”对象进行排序。

因此,如果两个项目具有相同的.transactionDate,那么这两个项目将另外按第二维度排序,例如单位价格降序。

编辑:我在下面工作,有没有更简洁的方式来写这个?

+(NSArray *)SortInvoiceItems:(NSArray *)items forSort:(SortItem*)sortItem forSecondarySort:(SortItem*)secondarySortItem {

    NSSortDescriptor *primaryDescriptor;
    NSSortDescriptor *secondaryDescriptor;

    switch(sortItem.state) {
        case DateAscending:
            primaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"transactionDate" ascending:YES];
            break;
        case DateDescending:
            primaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"transactionDate" ascending:NO];
            break;
        case SumAscending:
            primaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"netInvoiceAmount" ascending:YES];
            break;
        case SumDescending:
            primaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"netInvoiceAmount" ascending:NO];
            break;
        case UnitPriceAscending:
            primaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"uomNetAmt" ascending:YES];
            break;
        case UnitPriceDescending:
            primaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"uomNetAmt" ascending:NO];
            break;
        default: NSLog(@"invalid sort item");
    }

    switch(secondarySortItem.state) {
        case DateAscending:
            secondaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"transactionDate" ascending:YES];
            break;
        case DateDescending:
            secondaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"transactionDate" ascending:NO];
            break;
        case SumAscending:
            secondaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"netInvoiceAmount" ascending:YES];
            break;
        case SumDescending:
            secondaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"netInvoiceAmount" ascending:NO];
            break;
        case UnitPriceAscending:
            secondaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"uomNetAmt" ascending:YES];
            break;
        case UnitPriceDescending:
            secondaryDescriptor = [[NSSortDescriptor alloc] initWithKey:@"uomNetAmt" ascending:NO];
            break;
        default: NSLog(@"invalid sort item");
    }

    NSArray *sortDescriptors = @[primaryDescriptor, secondaryDescriptor];
    return [items sortedArrayUsingDescriptors:sortDescriptors];
}

第二次编辑:重写:

+(NSArray *)SortInvoiceItems:(NSArray *)items forPrimarySort:(SortItem*)primary forSecondarySort:(SortItem*)secondary {

    NSSortDescriptor *primaryDescriptor = [self GetDescriptorForSortItem:primary];
    NSSortDescriptor *secondaryDescriptor = [self GetDescriptorForSortItem:secondary];
    NSArray *sortDescriptors = @[primaryDescriptor, secondaryDescriptor];

    return [items sortedArrayUsingDescriptors:sortDescriptors];
}

+(NSSortDescriptor *)GetDescriptorForSortItem:(SortItem*)sortItem {
    switch(sortItem.state) {
        case DateAscending:
            return [[NSSortDescriptor alloc] initWithKey:kTransactionDateString ascending:YES];
        case DateDescending:
            return [[NSSortDescriptor alloc] initWithKey:kTransactionDateString ascending:NO];
        case SumAscending:
            return [[NSSortDescriptor alloc] initWithKey:kNetInvoiceAmount ascending:YES];
        case SumDescending:
            return [[NSSortDescriptor alloc] initWithKey:kNetInvoiceAmount ascending:NO];
        case UnitPriceAscending:
            return [[NSSortDescriptor alloc] initWithKey:kUOMNetAmount ascending:YES];
        case UnitPriceDescending:
            return [[NSSortDescriptor alloc] initWithKey:kUOMNetAmount ascending:NO];
        default:
            return [[NSSortDescriptor alloc] initWithKey:kTransactionDateString ascending:NO]; // default to date descending
    }
}

2 个答案:

答案 0 :(得分:1)

使用NSArray' -sortedArrayUsingDescriptors:来解决此问题。使用此方法,您可以提供一个NSSortDescriptor s数组,其中第二个将作为辅助排序(如果有第三个排序,它将是第三类排序等)。 / p>

您可以使用NSSortDescriptor创建-[NSSortDescriptor initWithKey:ascending:comparator:]并传递比较器块。

答案 1 :(得分:0)

使用NSSortDescriptor构造排序,如下所述:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html

修改: 在您的情况下,因为您有一个名为state的SortItem属性来确定排序描述符,并且因为您可以根据自己的意愿构建state类型,我建议您进行排序描述部分状态本身。这样,当需要排序时,没有工作要做:状态本身提供了您将使用的排序描述符,您可以摆脱SortInvoiceItems中的切换。一般来说,开关可以被视为一种恶劣气味,表明你没有正确设计你的对象类型;你应该让实际的对象知道该做什么而不是开启什么。