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


11 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;
}

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

Question

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

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

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

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




次の一般的な方法を目的に使用できます。 あなたの問題を解決するはずです。

//Called method
-(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending];
    [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
    return arrDeviceList;
}

//Calling method
[self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];



クイックソートを使用してカスタムオブジェクトの配列を並べ替えることができます。 Swift 4を使用して以下の例を見つけてください

func sortArrayOfPersonInAscendingOrder() {
        if self.arrSortingPersons != nil, self.arrSortingPersons.count > 0 {
            self.arrSortingPersons.sort(by: { (person1, person2) -> Bool in
                return person1.birthDate < person2.birthDate
            })
        }

        print("Sorted Array In Ascending Order:\n\(self.arrSortingPersons)")
    }



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



私の場合は、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)



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




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

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



Swiftのプロトコルと関数型プログラミングでは、クラスをComparableプロトコルに準拠させ、プロトコルで必要なメソッドを実装し、ソートされた(by:)高次関数を使用してソートされた配列を作成する必要がありませんところで、

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)



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

次に、 sortedArrayUsingSelector:@selector(compare:)と呼ぶことにします。

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




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];

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




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

//値をソートする

    [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






Related