3

I have a bit of a strange problem. So I have an array of dictionaries say,

(
Dict 1:
"Name" = "B"
"Number" = "2"

Dict 2:
"Name" = "A"
"Number" = "1"

Dict 3:
"Name" = "D"
"Number" = "4"

Dict 4:
"Name" = "C"
"Number" = "3"

Dict 5
"Name" = "E"
"Number" = "5"
)

And say I have an array:

(
"1"
"4"
"2"
)

How can I get an array that contains all the dictionaries that their "Number" key match each object in that array and have it sorted according to the second array?

e.g. output would be

(
Dict 1:
"Name" = "A"
"Number" = "1"

Dict 2:
"Name" = "D"
"Number" = "4"

Dict 3:
"Name" = "B"
"Number" = "2"
)

I think I can use sortedArrayUsingDescriptors but I'm not sure how to specify multiple descriptors. Can the descriptors contain every object in the array? Any help or guidance is much appreciated.

madLokesh
  • 1,860
  • 23
  • 49
Milo
  • 5,041
  • 7
  • 33
  • 59
  • how about doing this 2 steps: 1. sort original dictionary with key = number 2. for each number in your array {1,4,2..}, do a bsearch in your sorted dictionary, if found then you print the details of that entry complexity = O(mlogm + nlogm) m = size of dictionary, n = size of query array – shole Mar 21 '14 at 04:38
  • oh but something is unclear here, will your dictionary have two entries with same number? eg: Dict 1 { Name = A, number = 1} Dict 2 {Name = B, number = 1} If yes, then when you have 1 in your query array, should I print out both? – shole Mar 21 '14 at 04:39
  • @shole What do you mean by bsearch? And do you mean sorted array not dictionary? – Milo Mar 21 '14 at 04:41
  • @shole No, there will not be duplicates in the number key. – Milo Mar 21 '14 at 04:41
  • I meant binary search, can you reorder your dictionary in anyway such that it's ascending with the Number? For example, I can make array of pairs [(1,2), (2,1), (3,4), (4,3),(5,5)] which is in form of (DictID, Number), then reorder it to [(2,1),(1,2),(4,3),(3,4),(5,5)]. Finally just do binary search of each query, say for query {1,4,2}, I can find (2,1), (3,4), (1,2) respectively, so you know you should print Dict2 , Dict3, Dict1 as output.. – shole Mar 21 '14 at 04:48

4 Answers4

3

This has nothing to do with sorting - especially since not every dictionary in the array is even involved. What you want to do is extract each dictionary from the array.

This would be a lot simpler if you didn't have an array of dictionaries at all. Instead, you should start with one big dictionary where the key is the number and the value is whatever (perhaps the whole dictionary, perhaps the name alone). Now you can just look up each number as the key into that dictionary and grab the name.

{ 1 => A, 2 => B, 3 => C ...}

Now just grab objectForKey:@1, objectForKey:@4, objectForKey:@2 and you're done.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I'm pulling from a JSON request so I get an array of dictionaries. So unfortunately this will not work for me. +1 though. – Milo Mar 21 '14 at 04:45
  • I don't agree. You can _make_ the dictionary I am describing from the data that you get! And you should do so, exactly in order to facilitate the lookup that you intend to do. Clever, eh? – matt Mar 21 '14 at 04:48
  • This kind of re-jiggering in order to facilitate a certain kind of lookup is perfectly standard behavior. – matt Mar 21 '14 at 04:49
  • Yeah, it's a clever method I agree. I'll see what I can do. – Milo Mar 21 '14 at 04:49
1
for (NSNumber *aNumber in testArray) {
    for (NSDictionary *aDict in anArray) {
        if (aNumber.intValue == [(NSNumber *)[aDict valueForKey:@"Number"]intValue]) {
            [finalArray addObject:aDict];
        }
    }
}
A_G
  • 69
  • 2
0

Here is the answer. here I used enumerator, which is faster

NSArray * dicArray = @[@{@"Name": @"B",@"Number":@"2"},
                       @{@"Name": @"A",@"Number":@"1"},
                       @{@"Name": @"D",@"Number":@"4"},
                       @{@"Name": @"C",@"Number":@"3"},
                       @{@"Name": @"E",@"Number":@"5"}];
NSArray * indArray = @[@(1),@(4),@(2)];

NSMutableArray * resultArray = [NSMutableArray arrayWithCapacity:indArray.count];
[indArray enumerateObjectsUsingBlock:^(NSNumber* SearchValue, NSUInteger idx, BOOL *stop) {

    //search dicArray for object, which match your condition (i.e Number value == obj value)
    NSInteger index = [dicArray indexOfObjectPassingTest:^BOOL(NSDictionary* obj, NSUInteger idx, BOOL *stop) {
        return ([(NSString *)obj[@"Number"] integerValue] == SearchValue.integerValue)? YES : NO;
    }];

    resultArray[idx] = dicArray[index];
}];

NSLog(@"%@",resultArray);
Rajath Shetty K
  • 424
  • 3
  • 9
0

So I figured it out. Basically I used nested for-loops.

Here is the code. It may take a long time depending on how many objects are in each. For me I had about 30 objects each so it took about 50ms:

NSMutableArray *finalArray = [NSMutableArray array];
for (NSString *keyName in keyArray) {
    NSString *fname;
    for (NSDictionary *dict in dictArray) {
        fname = [dict objectForKey:@"theKey"];
        if ([fname isEqualToString:keyName])
            [finalArray addObject:dict];
    }
}
Milo
  • 5,041
  • 7
  • 33
  • 59