9

並べて並べ替える必要がある配列がいくつかあります。

たとえば、最初の配列には名前:@[@"Joe", @"Anna", @"Michael", @"Kim"]があり、もう一方の配列にはアドレス:@[@"Hollywood bld", @"Some street 3", @"That other street", @"country road"]があり、配列のインデックスが一緒になっています。「ジョー」は「ハリウッドビル」などに住んでいます。

名前配列をアルファベット順に並べ替えてから、アドレス配列を並べて並べ替えて、「ハリウッド bld」が「ジョー」と同じインデックスを持つようにしたいと思います。1つの配列をアルファベット順にソートする方法を知っています

NSSortDescriptor *sort=[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO];
[myArray sortUsingDescriptors:[NSArray arrayWithObject:sort]];

しかし、2 番目の配列を適切な順序で並べ替える簡単な方法はありますか?

4

4 に答える 4

11
  1. 順列配列を作成します。初期設定はp[i]=i
  2. name最初の配列のキーに従って順列をソートします
  3. 順列を使用して両方の配列を並べ替えます

例: 最初の配列が{"quick", "brown", "fox"}. 順列は から始まり、ソート後になります{0, 1, 2}{1, 2, 0}これで、順列配列を調べて、元の配列と 2 番目の配列を必要に応じて並べ替えることができます。

NSArray *first = [NSArray arrayWithObjects: @"quick", @"brown", @"fox", @"jumps", nil];
NSArray *second = [NSArray arrayWithObjects: @"jack", @"loves", @"my", @"sphinx", nil];
NSMutableArray *p = [NSMutableArray arrayWithCapacity:first.count];
for (NSUInteger i = 0 ; i != first.count ; i++) {
    [p addObject:[NSNumber numberWithInteger:i]];
}
[p sortWithOptions:0 usingComparator:^NSComparisonResult(id obj1, id obj2) {
    // Modify this to use [first objectAtIndex:[obj1 intValue]].name property
    NSString *lhs = [first objectAtIndex:[obj1 intValue]];
    // Same goes for the next line: use the name
    NSString *rhs = [first objectAtIndex:[obj2 intValue]];
    return [lhs compare:rhs];
}];
NSMutableArray *sortedFirst = [NSMutableArray arrayWithCapacity:first.count];
NSMutableArray *sortedSecond = [NSMutableArray arrayWithCapacity:first.count];
[p enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSUInteger pos = [obj intValue];
    [sortedFirst addObject:[first objectAtIndex:pos]];
    [sortedSecond addObject:[second objectAtIndex:pos]];
}];
NSLog(@"%@", sortedFirst);
NSLog(@"%@", sortedSecond);
于 2012-09-15T11:33:36.383 に答える
10

まず、このように 2 つの配列を並列に並べ替える必要があるアーキテクチャを再検討することをお勧めします。ただし、2 つの配列の要素をペアに保持する辞書の一時的な配列を作成することで、それを行うことができます。

次に、結合された配列を並べ替え、2 つの配列を再度抽出し、要求どおりに並べ替えます。

元のデータ:

NSArray *names     = @[@"Joe", @"Anna", @"Michael"];
NSArray *addresses = @[@"Hollywood bld", @"Some street 3", @"That other street"];

実際の並べ替えコード:

NSMutableArray *combined = [NSMutableArray array];

for (NSUInteger i = 0; i < names.count; i++) {
    [combined addObject: @{@"name" : names[i], @"address": addresses[i]}];
}

[combined sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]];

names     = [combined valueForKey:@"name"];
addresses = [combined valueForKey:@"address"];

valueForKey:配列で使用すると、同じサイズの新しい配列が抽出され、元の配列内のオブジェクトのプロパティが取り込まれていることに注意してください。この場合、元の配列から新しい配列を作成し、必要に応じて並べ替えます。

このアプローチは数行のコードしか必要とせず、必要に応じて簡単に追跡およびデバッグできます。

于 2012-10-06T13:40:50.863 に答える
5

最善の方法は、配列を 1 つだけ持つようにデータを再構築することです。あなたの例では、名前とアドレスの両方を持つ新しいクラスを作成し、それらを配列に入れて名前でソートするのが最も理にかなっています。

于 2012-09-15T11:29:20.047 に答える
3

おそらく、ソートの前後にオブジェクトのインデックスを追跡することでこれを行うことができますが、これらすべてのプロパティを持つ単一のオブジェクトを持つ方が簡単かもしれません

Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *addresss;

次に、これらのオブジェクトを単一の配列に保存します。この配列はname、またはaddressキーパスで並べ替えることができます

于 2012-09-15T11:28:24.450 に答える