5

各期間の終了とその長さを示す属性 endCalYear、endMonth、および periodLength などの期間ベースの情報を含むカスタム オブジェクトがあります。

NSSortDescriptorこれら 3 つの属性を組み合わせて、このオブジェクトを 3 つのキーすべてで同時にソートできる、ベースのソート方法またはその他のソート方法を作成したいと考えています。

例:

EndCalYear  endMonth  periodLength (months) sortOrder
2012        6         6                     1
2012        6         3                     2
2012        3         3                     3
2011        12        12                    4

ソートアルゴリズムは、私自身のアルゴリズムに基づいて完全に任意です。

そのようなアルゴリズムをどのようにコーディングできますか?

ブロック ベースのsortDescriptorWithKey:ascending:comparator:方法は、1 つの並べ替えキーしか指定できないため、私の見解では機能しません。ただし、3 つのキーすべてを同時にソートする必要があります。

これを解決する方法についてのアイデアや考えはありますか?

ありがとうございました!

4

2 に答える 2

22

代わりにブロックで並べ替えることができます。

NSArray *sortedArray;
sortedArray = [myArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    MyObject *first = (MyObject*)a;
    MyObject *second = (MyObject*)b;

    if (first.endCalYear < second.endCalYear) {
        return NSOrderedAscending;
    }
    else if (first.endCalYear > second.endCalYear) {
        return NSOrderedDescending;
    }
    // endCalYear is the same

    if (first.endMonth < second.endMonth) {
        return NSOrderedAscending;
    }
    else if (first.endMonth > second.endMonth) {
        return NSOrderedDescending;
    }    
    // endMonth is the same

    if (first.periodLength < second.periodLength) {
        return NSOrderedAscending;
    }
    else if (first.periodLength > second.periodLength) {
        return NSOrderedDescending;
    }
    // periodLength is the same

    return NSOrderedSame;
}]

これendCalYearは、昇順、endMonth昇順、最後にperiodLength昇順で並べ替えられます。順序を変更するように変更するか、ifステートメントの符号を切り替えて降順にすることができます。

NSFetchedResultsControllerの場合は、別のことを試してみてください。

並べ替える列ごとに1つずつ、記述子のリストを渡すことができるようです。

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSSortDescriptor *descriptor1 = [[NSSortDescriptor alloc] initWithKey:@"endCalYear" ascending:YES];
NSSortDescriptor *descriptor2 = [[NSSortDescriptor alloc] initWithKey:@"endMonth" ascending:YES];
NSSortDescriptor *descriptor3 = [[NSSortDescriptor alloc] initWithKey:@"periodLength" ascending:YES];
NSArray *sortDescriptors = @[descriptor1, descriptor2, descriptor3];
[fetchRequest setSortDescriptors:sortDescriptors];
于 2012-10-16T15:20:29.143 に答える
7

並べ替え用の API は、通常、NSSortDescriptors1 つだけでなく の配列を使用できます。

たとえば、オブジェクトの配列を取る (複数形に注意)NSArrayというメソッドがあります。sortedArrayUsingDescriptors:NSSortDescriptor

したがって、次のように簡単に書くことができます。

NSSortDescriptor *endCalYearSD = [NSSortDescriptor sortDescriptorWithKey:@"endCalYear" ascending:YES];
NSSortDescriptor *endMonthSD = [NSSortDescriptor sortDescriptorWithKey:@"endMonth" ascending:YES];
NSSortDescriptor *periodLenSD = [NSSortDescriptor sortDescriptorWithKey:@"periodLength" ascending:YES];

NSArray *sortedArray = [originalArray sortedArrayUsingDescriptors:@[endCalYearSD, endMonthSD, periodLenSD]];

このように、originalArray最初に endCalYear でソートされ、同じ endCalYear を持つ各エントリが endMonth でソートされ、同じ endCalYear と endMonth を持つ各エントリが periodLendth でソートされます。

ソートを提案するほとんどの API (CoreData などを含む) で sortDescriptors の配列を使用する API があるため、原則は常に同じです。


本当に1つだけに固執する必要がある場合NSSortDescriptor(およびソートアルゴリズムがブロックベースのコンパレータまたはの配列を使用するほど柔軟でない場合NSSortDescriptors)、カスタムオブジェクトにプロパティを提供して、値を計算することができます。ソートアルゴリズムのベース。

たとえば、そのようなメソッドをカスタム クラスに追加します。

-(NSUInteger)sortingIndex {
    return endCalYear*10000 + endCalMonth*100 + periodLength;
}

次に、このキー/プロパティで並べ替えます。これは読みやすく、非常にきれいなデザイン パターンではありませんが、ソート アルゴリズム API を変更して一度に複数のキーでソートできるようにすることをお勧めします。</p>


[EDIT] (ブロックベースの API で [EDIT] に回答するため)

ブロックベースの API が機能しない理由がわかりませんsortDescriptorWithKey:ascending:comparator:。そこで必要なカスタムNSComparatorブロックを指定できるため、このブロックは 2 つのオブジェクトが与えられた場合に、どちらが前にあるかを判断できます。どれがどれより前にあるかを判断する方法はあなた次第です。比較できるのは、、、、などだけなのでendCalYear、ここでは複数のキーを使用した並べ替えに関する制限はありません。endCalYearendMonth

于 2012-10-16T16:09:17.157 に答える