0
votes

I am trying to sort an array of NSDictionaries into an alphabatised array of arrays based of one of the NSDictionary valueForKey: first letters

effectively I want something that looks a little something like this

Array A // contains NSDictionaies with keyvalue MAF strings starting with A
 NSDictionary1
 NSDictionary2
 NSDictionary3
Array B // contains NSDictionaies with keyvalue MAF strings starting with B
 NSDictionary1
 NSDictionary2
 NSDictionary3
Array C // contains NSDictionaies with keyvalue MAF strings starting with C
 NSDictionary1
 NSDictionary2
 NSDictionary3
etc

So I have an array of Letters and inside each letter array I would like to have an Array of NSDictionary values that keyValue MAFs first letter should match.

So far I have an array of dictionaries that I have sorted like so

NSSortDescriptor *sortDescriptor;
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"MAF"
                                                      ascending:YES];
        NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
        sortedDictionaryArray = [arrayData sortedArrayUsingDescriptors:sortDescriptors]; // use this in cellforrow: and didselectrow:

        NSLog(@"%@", sortedDictionaryArray); // this gives me a sorted array of NSdictionaries based off their MAF keyvalue.

This is what the NSDicitonary looks like

HADM = 1;
ISLOT = 0;
ISVERT = 0;
MAF = "Yazot"; // keyvalue I am trying to work with.

Then I get stuck, I am not sure where to go from here. if anyone could help me understand how to create an NSArray of NSArrays NSDictionaries that would be great! hopefully I have explained what I am trying to do correctly, if you need any more details just let me know and I will supply.

2
What does the data look like initially? Just a bunch of dictionaries in a single array? - mattyohe
yep, sorted alphabetically by the string in the MAF keyvalue of the NSDictionary Object. - HurkNburkS
Do they need to be sorted in the final arrays? If so, then why not enumerate the initial list, put them in each lettered array, and then sort each of those letter arrays separately? If not, then just enumerate and don't do the last sort. - mattyohe
they need to be sorted in their final instance.. where they are in the array of arrays... okay going to look up enumerate now and see what I can do. - HurkNburkS
The issue I have is not knowing the code to check the dictionaries keyvalue... or something like that. man this is killing me lol - HurkNburkS

2 Answers

2
votes

This code will first sort your array of dictionaries by using the objects assigned to the key @"MAF". Than it will create a new Dictionary where it will add a mutable array for each first letter of that string and add the object to it.

NSArray *array = @[@{@"MAF": @"Yazot"}, @{@"MAF": @"Lorem"},@{@"MAF": @"Ipsum"}, @{@"MAF": @"Laura"},@{@"MAF": @"Isit"}];

NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
    return [obj1[@"MAF"] compare:obj2[@"MAF"]];
}];

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

for (NSDictionary *dict in sortedArray) {
    NSString *firstLetter = [dict[@"MAF"] substringToIndex:1];

    if(![[dictionary allKeys] containsObject:firstLetter])
        dictionary[firstLetter] = [NSMutableArray array];

    [dictionary[firstLetter] addObject:dict];

}

if you need case insensitive string handling, "L" and "l" should be put into the same array, do

NSArray *array = @[@{@"MAF": @"Yazot"}, @{@"MAF": @"Lorem"},@{@"MAF": @"Ipsum"}, @{@"MAF": @"Laura"},@{@"MAF": @"Isit"}];

NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
    return [obj1[@"MAF"] caseInsensitiveCompare:obj2[@"MAF"]];
}];

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

for (NSDictionary *dict in sortedArray) {
    NSString *firstLetter = [dict[@"MAF"] substringToIndex:1];
    firstLetter = [firstLetter lowercaseString];
    if(![[dictionary allKeys] containsObject:firstLetter])
        dictionary[firstLetter] = [NSMutableArray array];

    [dictionary[firstLetter] addObject:dict];

}

dictionary results in

{
    i =     (
                {
            MAF = Ipsum;
        },
                {
            MAF = Isit;
        }
    );
    l =     (
                {
            MAF = Laura;
        },
                {
            MAF = Lorem;
        }
    );
    y =     (
                {
            MAF = Yazot;
        }
    );
}
1
votes

We can start by creating a dictionary of arrays of dictionaries.

NSMutableDictionary *dictsForFirstLetter = [[NSMutableDictionary alloc] init];

for (NSDictionary *dict in arrayData) {
    NSString *dictMAF = dict[@"MAF"];
    NSString *firstLetter = [[dictMAF substringToIndex:1] uppercaseString];
    NSMutableArray *dicts = dictsForFirstLetter[firstLetter];
    if (!dicts) {
        dicts = [[NSMutableArray alloc] init];
        dictsForFirstLetter[firstLetter] = dicts;
    }
    [dicts addObject:dict];
}

Then you can retrieve the array of dictionaries by the first letter of their MAF value:

NSArray *dicts = dictsForFirstLetter[@"Y"];

To get an alphabetized array from this, you can sort the dictionary's keys and enumerate over them:

NSMutableArray *alphabetizedDicts = [[NSMutableArray alloc] init];

NSArray *firstLetters = [dictsForFirstLetter allKeys];
NSArray *sortedFirstLetters = [firstLetters sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];

for (NSString *firstLetter in sortedFirstLetters) {
    NSArray *dicts = dictsForFirstLetter[firstLetter];
    [alphabetizedDicts addObject:dicts];
}