ios - transaction - rlmresults objectswhere




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

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

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

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

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


Swiftの配列を並べ替える

Swifty Personの場合、上記の目標をグローバルに達成するための非常にクリーンなテクニックです。 いくつかの属性を持つUserサンプルカスタムクラスがあります。

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

これで、 createdDate基づいて昇順または降順に並べ替える必要がある配列ができました。 だから日付比較のための関数を追加することができます。

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

今度は、 UserためにArray extensionを持つことができます。 簡単な言い方をすれば、その中にUserオブジェクトしか持たないArrayのメソッドだけを追加することができます。

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

昇順での使用

let sortedArray = someArray.sortUserByDate(.orderedAscending)

降順での使用

let sortedArray = someArray.sortUserByDate(.orderedAscending)

同じ注文のための使用法

let sortedArray = someArray.sortUserByDate(.orderedSame)

上記のextensionメソッドは、 Arrayの型が[User] ||の場合にのみアクセス可能です。 Array<User>


比較方法

あなたのオブジェクトの比較メソッドを実装するか、

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

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

NSSortDescriptor(より良い)

または通常より良い:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

配列に複数のキーを追加することで、複数のキーで簡単にソートできます。 カスタムコンパイラーメソッドの使用も可能です。 ドキュメントを見てください。

ブロック(輝いている!)

また、Mac OS X 10.6とiOS 4以降のブロックで並べ替えることも可能です:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

パフォーマンス

後者はKVCに依存しているため、 -compare:とブロックベースのメソッドはNSSortDescriptorを使用するよりもかなり高速になります。 NSSortDescriptorメソッドの主な利点は、コードではなくデータを使用してソート順を定義する方法を提供することで、ヘッダー行をクリックしてNSTableViewをソートできるように設定することが容易になります。


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)

iOS 4ブロックはあなたを救います:)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html少しの説明


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)

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

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

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

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


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

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

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


ソートNSMutableArrayは非常に簡単です:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];

私の場合は、配列をソートするために "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

私はObjectiveCLinqと呼ばれるカテゴリメソッドの小さなライブラリを作成しました。これは、この種のものをより簡単にします。 キーセレクタでsortメソッドを使用すると、次のようにbirthDateソートできます。

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]

私はすべてを試みたが、これは私のために働いた。 あるクラスでは、 " crimeScene "という別のクラスがあり、 " crimeScene "のプロパティでソートしたいと思っています。

これは魅力のように機能します:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

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

//値をソートする

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

NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");

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

ありがとう、それは正常に動作しています...





nsmutablearray