ios カスタムオブジェクトを含むNSMutableArrayをどのようにソートするのですか?





12 Answers

NSMutableArrayメソッドsortUsingFunction:context:参照してくださいsortUsingFunction:context:

2つのオブジェクト(2つのPersonオブジェクトを比較するため、 Person型の)とコンテキストパラメータを取る比較関数を設定する必要があります。

2つのオブジェクトは、 Person単なるインスタンスです。 3番目のオブジェクトは文字列です(例:@ "birthDate")。

この関数は、 NSComparisonResult返しますPersonA.birthDate < PersonB.birthDate場合、 PersonA.birthDate返します。 PersonA.birthDate > PersonB.birthDate場合はPersonA.birthDate PersonB.birthDateます。 最後に、 PersonA.birthDate == PersonB.birthDate場合はPersonA.birthDate PersonB.birthDateます。

これは大雑把な擬似コードです。 あなたは、ある日付が別の日付に「より小さい」「より多く」「等しい」(例えば、時代遅れの秒数を比較するなどの)意味を果たす必要があります。

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

よりコンパクトなものを望むなら、三項演算子を使うことができます:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

あなたがこれをたくさんするなら、インライン展開はおそらくこれを少し速めることができます。

ios objective-c sorting cocoa-touch nsmutablearray

私がやりたいことはかなりシンプルなようですが、ウェブ上で何の答えも見つけられません。 私はオブジェクトのNSMutableArrayを持っていて、それらが 'Person'オブジェクトだとしましょう。 NSMutableArrayをNSDateであるPerson.birthDateでソートしたい。

私はそれがこの方法と関係があると思う:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

Javaでは、オブジェクトをComparableに実装するか、インラインカスタムコンパレータでCollections.sortを使用します... Objective-Cではどのようにしてこの作業を行いますか?




iOS 4以降、ソートにブロックを使用することもできます。

この特定の例では、配列内のオブジェクトにNSIntegerを返す 'position'メソッドがあると仮定しています。

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

注:ソートされた配列はオートレリースされます。




GeorgSchöllyの2番目の答えには欠けているステップがありますが、 うまくいきます。

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptor:sortDescriptors];



あなたのPersonオブジェクトは、別のPersonオブジェクトを受け取り、2つのオブジェクト間の関係に従ってNSComparisonResultを返す、メソッドcompare:を実装する必要があります。

次に、 sortedArrayUsingSelector:@selector(compare:)と呼びます。これを行う必要があります。

他の方法もありますが、私が知る限り、 ComparableインターフェイスのCocoa-equivはありません。 sortedArrayUsingSelector:を使用すると、おそらく最も無痛な方法です。




NSMutableArray場合は、 sortUsingSelectorメソッドを使用します。 新しいインスタンスを作成することなく、場所をソートします。




NSNumbers配列を並べ替えるだけのNSNumbers 、1つの呼び出しで並べ替えることができます:

[arrayToSort sortUsingSelector: @selector(compare:)];

これは、配列内のオブジェクト( NSNumberオブジェクト)がcompareメソッドを実装するために機能します。 NSStringオブジェクトや、compareメソッドを実装するカスタムデータオブジェクトの配列に対しても、同じことができます。

コンパレータブロックを使用したコードの例を次に示します。 各辞書がキー "sort_key"に数字を含む辞書の配列をソートします。

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

上のコードは、各ソートキーの整数値を取得して比較する作業を示しています。 NSNumberオブジェクトはcompareメソッドを実装するので、はるかに簡単に書き直すことができます:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

コンパレータの本体を1行に蒸留することもできます:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

私は、コードが読みやすく、デバッグしやすいので、単純なステートメントとたくさんの一時変数を好む傾向があります。 いずれにしても、コンパイラは一時変数を最適化するので、オールインワン版の利点はありません。




私はちょうどカスタム要件に基づいて複数のレベルの並べ替えを行った。

//値をソートする

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec




-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}



NSComparatorを使用してソートする

カスタムオブジェクトをソートする場合は、カスタムオブジェクトを比較するために使用するNSComparatorを用意する必要があります。 ブロックは、2つのオブジェクトの順序を示すNSComparisonResult値を返します。 配列全体をソートするために、 NSComparatorは次のように使用されます。

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

NSSortDescriptorを使用した並べ替え
例として、カスタムクラスのインスタンスを含む配列があると仮定しましょう。従業員の属性はfirstname、lastname、およびageです。 次の例は、配列の内容を年齢キーで昇順にソートするために使用できるNSSortDescriptorを作成する方法を示しています。

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

カスタム比較を使用して並べ替える
名前は文字列であり、文字列を並べ替えてユーザーに提示するときは、常にローカライズされた比較を使用する必要があります。 また、大文字と小文字を区別しない比較を実行することもよくあります。 ここでは、(localizedStandardCompare :)を使用して、最後と最初の名前で配列を並べ替える例を示します。

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

参考および詳細な説明は、 https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html : https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.htmlを参照してhttps://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html
http://www.ios-blog.co.uk/tutorials/objective-c/how-to-sort-nsarray-with-custom-objects/




私の場合は、配列をソートするために "sortedArrayUsingComparator"を使用します。 以下のコードを見てください。

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

私の目的は、

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end



sortDescriptorを作成してから、以下のようにsortDescriptorを使ってnsmutablearrayをソートすることができます。

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)



NSSortDescriptor  *sort = [[NSSortDescriptor alloc] initWithKey:@"_strPrice"
                                                 ascending:sortFlag selector:@selector(localizedStandardCompare:)] ;



Related