日付文字列またはオブジェクトのNSArrayを並べ替える


86

次のようなNSArray日付文字列(つまりNSString)を含むがあります: "Thu、21 May 09 19:10:09 -0700"

NSArray日付で並べ替える必要があります。NSDate最初に日付文字列をオブジェクトに変換することを考えましたが、NSDateオブジェクトで並べ替える方法に行き詰まりました。

ありがとう。


これはFoundationフレームワークに関連しており、iPhoneに固有ではないため、再タグ付けされています。
クインテイラー

回答:


110

日付をNSDateオブジェクトとしてNS(Mutable)Arrayに格納し、-[NSArray sortedArrayUsingSelector:または-[NSMutableArray sortUsingSelector:]を使用@selector(compare:)してパラメーターとして渡します。この-[NSDate compare:]メソッドは、日付を昇順で並べ替えます。これは、を作成するNSSortDescriptorよりも簡単で、独自の比較関数を作成するよりもはるかに簡単です。(NSDateオブジェクトは、少なくともカスタムコードで達成したいと思うのと同じくらい効率的に相互に比較する方法を知っています。)


11
元の質問が日付の配列の並べ替えについて尋ねていたのか、それとも日付フィールドを持つオブジェクトの配列の並べ替えについて尋ねていたのかは明確ではありません。前者の場合はこれが最も簡単なアプローチですが、後者の場合はNSSortDescriptorが最適です。
smorgan 2009

@smorgan NSSortDescriptorはnil日付をどのように処理しますか?
アッシュ

あなたの助けに感謝します、私たちはApple Docsでもっと読むべきだと思います、しかしあなたがそれを使うまでそれはとても退屈に思えます。
abo3atef 2013

1
例として、これをスニペットコードで示していただけますか?前もって感謝します。
uplearnedu.com 2014

115

NSMutableArrayタイプが「beginDate」のフィールドを持つオブジェクトがあれば、以下のようにNSDate使用NSSortDescriptorします。

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE];
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

3
かなりの時間が経過したことは知っていますが(前の回答が受け入れられたとき、NSSortDescriptorはまだ存在しない可能性があります)、将来の使用のために、これが適切な回答になるはずです。
Viveの

1
これは素晴らしいソリューションです。code.Thanxトン@vinzenzweberの数行に私の問題を解決
Pratyusha Terli

1
本当に...私は実際にこれが最初の実行で機能したことにショックを受けました!initWithKeyは、キーが定義されている辞書用に予約されていると思いましたが、必要なのは、オブジェクトの配列内のプロパティを参照することだけですか?光を輝かせましょうvinzenzweberskavitchski !!
whyoz 2012年

NSSortDescriptorは、2003年後半のOS X 10.3以降に存在します。これは少し異なるシナリオであり、日付は別のオブジェクトのフィールドです。さらに最新のAPIでは、-[NSMutableArray sortUsingComparator:](10.6+)を使用-compare:して、2つのフィールドの呼び出し結果を返すブロックを渡すこともできます。おそらく-valueForKey:、各オブジェクトを呼び出すよりも高速です。-sortWithOptions:usingComparator:オプションを使用して渡すことで、同時に並べ替えることもできます。
クインテイラー

上記のNSSortDescriptorはnil日付をどのように処理しますか?もしそうなら、どのように彼らをどうするかをデセクリプターに伝える必要がありますか?
アッシュ

17

次のようなものを使用することもできます。

//Sort the array of items by  date
    [self.items sortUsingComparator:^NSComparisonResult(id obj1, id obj2){
        return [obj2.date compare:obj1.date];
    }];

しかし、これは日付がNSDateむしろとして保存されていることを前提としてNStringいます。これは作成/実行に問題がないはずです。できれば、データを生の形式で保存することもお勧めします。このような状況での操作が簡単になります。


9

ブロックを使用して、次の場所で並べ替えることができます。

sortedDatesArray = [[unsortedDatesArray sortedArrayUsingComparator: ^(id a, id b) {
    NSDate *d1 = [NSDate dateWithString: s1];
    NSDate *d2 = [NSDate dateWithString: s2];
    return [d1 compare: d2];
}];

日付項目よりも多くの回数変換を行わないように、並べ替える前にすべての文字列を日付に変換することをお勧めします。どのソートアルゴリズムでも、配列内のアイテムの数よりも多くの文字列から日付への変換が得られます(場合によっては大幅に多くなります)

ブロックの並べ替えについてもう少し詳しく説明します:http//sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html


これは、@ notoopによって提示された同じ準最適なアイデアの変形です。いずれにせよ、最初にNSDateに変換することは間違いなく進むべき道です。
クインテイラー

彼は基本的に@notoopの答えで私の答えを入れました.....あなたが私に尋ねた場合、それらを二重に投稿する必要はまったくありません....
TheCodingArt 2013年

これは、日付文字列をNSDateの配列に解析してから、NSDateの配列を並べ替えるよりもはるかに低速です。これにより、文字列の2 *(n-1)倍の余分な解析が発生します。文字列の解析は、一般的にCPUで大変な作業です。
CarlLee 2014

5

私の場合は次のように機能しました。

    NSArray * aUnsorted = [dataToDb allKeys];
    NSArray * arrKeys = [aUnsortedsortedArrayUsingComparator:^ NSComparisonResult(id obj1、id obj2){
        NSDateFormatter * df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@ "dd-MM-yyyy"];
        NSDate * d1 = [df dateFromString:(NSString *)obj1];
        NSDate * d2 = [df dateFromString:(NSString *)obj2];
        return [d1 compare:d2];
    }];

私は辞書を持っていました。そこでは、すべてのキーの日付がdd-MM-yyyyの形式になっています。また、allKeysはソートされていない辞書キーを返すため、データを時系列で表示したいと思いました。


5

を使用できますsortedArrayUsingFunction:context:。サンプルは次のとおりです。

NSComparisonResult dateSort(NSString *s1, NSString *s2, void *context) {
    NSDate *d1 = [NSDate dateWithString:s1];
    NSDate *d2 = [NSDate dateWithString:s2];
    return [d1 compare:d2];
}

NSArray *sorted = [unsorted sortedArrayUsingFunction:dateSort context:nil];

を使用するNSMutableArray場合は、sortArrayUsingFunction:context:代わりにを使用できます。


9
これは悪い考えです。比較関数は高速である必要があり、比較ごとに文字列からNSDateオブジェクトを作成する必要はありません。すでに-[NSDatecompare:]を使用している場合は、日付を配列に格納し、-sortedArrayUsingSelector:を直接使用します。
クインテイラー

ただし、すでにNSDateフィールドがあるオブジェクトを並べ替える場合は、これは良い解決策だと思います。番号?
GnarlyDog 2012

1
配列にすでにNSDateオブジェクトが含まれている場合は、上記の私の答えを使用するか-[NSMutableArray sortUsingComparator:]、10.6で追加されたを使用することもできます。
クインテイラー

NSStringとしてdateのKey-Valueオブジェクトが他のいくつかのKey-Valueオブジェクトとともに存在する辞書の配列を使用している場合、このソリューションはこれまでのところ最良です。dateSort関数内で少し変更する必要があります。いいぞ!:)
エルファン2015

4

を取得したらNSDateNSSortDescriptorwithinitWithKey:ascending:を作成し、を使用sortedArrayUsingDescriptors:して並べ替えを行うことができます。


このアプローチは機能しますが、-sortedArrayUsingSelector:の使用は少し簡単で、追加のオブジェクトを作成する必要はありません。
クインテイラー

事前編集では、質問に「「日付」キー」と記載されていたため、これは実際には、生の日付の配列ではなく、1つのフィールドとして日付を持つオブジェクト/辞書の配列であると想定しました。その場合、sortedArrayUsingSelector:は、ルックアップを実行するためのカスタムソートルーチンを作成する必要があるため、より複雑です。
smorgan 2009

ええ、混乱してすみません—彼が配列を「日付」キーで格納していると言っていたので、その参照をクリーンアップしました。それが質問をさらに混乱させることに気づきました。より複雑なデータ構造を考えると、相対的な複雑さについては間違いなく正しいです。
クインテイラー


1

これを変える

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE];
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Date" ascending:TRUE];
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

キーを変更するだけです。Date常にキーを変更する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.