Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting two NSArrays together side by side

I have several arrays that need to be sorted side by side.

For example, the first array has names: @[@"Joe", @"Anna", @"Michael", @"Kim"], and and the other array holds addresses: @[@"Hollywood bld", @"Some street 3", @"That other street", @"country road"], where the arrays' indexes go together. "Joe" lives at "Hollywood bld" and so on.

I would like to sort the names array alphabetically, and then have the address array sorted alongside so they still go together, with "Hollywood bld" having same index as "Joe". I know how to sort one array alphabetical with

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

But is there any easy way of getting the second array sorted using the appropriate order?

like image 429
Dan Mikkelsen Avatar asked Sep 15 '12 11:09

Dan Mikkelsen


People also ask

How do I sort two arrays together?

Write a SortedMerge() function that takes two lists, each of which is unsorted, and merges the two together into one new list which is in sorted (increasing) order. SortedMerge() should return the new list.

How do you merge two sorted arrays into a single sorted array?

print(arr2[x] + " "); The sorted arrays are merged into a single array using a while loop. After the while loop, if any elements are left in arr1 or arr2, then they are added to the merged array.


4 Answers

  1. Create a permutation array, initially set to p[i]=i
  2. Sort the permutation according to the name key of the first array
  3. Use the permutation to re-order both arrays

Example: let's say the first array is {"quick", "brown", "fox"}. The permutation starts as {0, 1, 2}, and becomes {1, 2, 0} after the sort. Now you can go through the permutation array, and re-order the original array and the second array as needed.

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);
like image 160
Sergey Kalinichenko Avatar answered Nov 16 '22 00:11

Sergey Kalinichenko


First off, you might want to re-consider an architecture that requires you to sort two arrays in a parallel fashion like this. But having said that, you can do it by creating a temporary array of dictionaries that keep the elements of the two arrays paired.

Then you sort the combined array, and extract the two arrays again, sorted as requested:

Original data:

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

The actual sorting code:

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

Notice that valueForKey: used on an array extracts a new array with the same size, populated with the properties of the objects in the original array. In this case, it create new arrays from the original ones, sorted as wanted.

This approach only requires a few lines of code and is easy to follow and debug, if needed.

like image 34
Monolo Avatar answered Nov 16 '22 00:11

Monolo


The best way is to restructure your data so that you only have one array. In your example, it would make most sense to create a new class with both name and address, put those in an array and sort it by name.

like image 24
Phillip Mills Avatar answered Nov 15 '22 23:11

Phillip Mills


You could probably do this by keeping track of indexes of objects before and after the sort but maybe it would be easier having a single object which hass all of these properties

Person : NSObject

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

Then you store these objects into a single array which you can sort by name, or address key paths

like image 20
wattson12 Avatar answered Nov 16 '22 00:11

wattson12