1
for(id key in stats) {
    NSLog(@"key=%@ value=%@", key, [stats objectForKey:key]);
}

I have a dictionary of arrays, and each of these arrays has a number of arrays itself. Its a multidimensional array in a dictionary.

However the above code gives me the following

2012-11-30 21:36:07.203 key=main cat c value=(
"<Food: 0x6e5fb70>"
)
2012-11-30 21:36:07.205 key=main cat b value=(
"<Food: 0x6e5fa00>",
"<Food: 0x6e5faa0>"
)
2012-11-30 21:36:07.207 key=bakery_products value=(
"<Food: 0x6e5f510>",
"<Food: 0x6e5f660>",
"<Food: 0x6e5f700>",
"<Food: 0x6e5f810>",
"<Food: 0x6e5f900>",
"<Food: 0x6e5d5d0>"
)

How can I access the values in those arrays that are being displayed as Food 0x6e5fb70 ?

I've literally been at it for hours now and cannot find a solution.

dev
  • 900
  • 2
  • 12
  • 26

3 Answers3

3

Something like this perhaps:

for (id key in [stats allKeys]) {
    NSArray *foodArray = [stats objectForKey:key];
    for (Food *food in foodArray) {
        // do stuff with Food object
    }
}

Update (for Ploto's 2nd comment):

Do you mean this:

NSArray *array = [stats objectForKey:@"bakery_products"];

Update #2 for description:

- (NSString *)description {
    return [NSString stringWithFormat:@"Food: %@, %@", whatever1, whatever2];
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • That is fantastic, however there is another side to this code! Could you please tell me how to select arrays in an object(array) according to a specific key? – dev Nov 30 '12 at 21:48
  • Arrays are not accessed by key, dictionaries are. Arrays are accessed by index. If there is more to your question then you should update your question with more information. – rmaddy Nov 30 '12 at 21:50
  • Basically I just want to access an array and its contents according to the key it represents. eg to get all the info in the arrays from dictionary key bakery_products? – dev Nov 30 '12 at 21:55
  • See my updated answer. Is this even close to what you mean? You are not being very clear at all. You really need to better describe your data structures and what you have and what you want. – rmaddy Nov 30 '12 at 22:24
  • That is very close. However I am still trying to print out everything contained in the dictionary or every array within the dictionary. If you could provide the code to print the dictionary flat that would be great.. – dev Nov 30 '12 at 22:36
  • Your original code was printing the dictionary, at least every key and value in it. IF you want to see what is in each `Food` object then you need to implement the `-(NSString *)description` method in your `Food` class. – rmaddy Nov 30 '12 at 22:39
  • Please show me how, its is quite late here and I have been working all day. :( – dev Nov 30 '12 at 22:42
  • Since I know nothing about your `Food` class, I can't. Add the method. Return a string that contains whatever data you want to display for the `Food` class. See my updated answer for a rough pattern. – rmaddy Nov 30 '12 at 22:45
  • @Pluto: For the description method, you just return a string that includes whatever info you want to describe your Foods. For example, you might implement it as `return [NSString stringWithFormat:@"Food %@ -- Calories: %d; Cost: %d; Ingredients: %@", self.name, self.calories, self.priceInDollars, self.ingredientList];`. – Chuck Dec 01 '12 at 00:21
0

On top of what @rmaddy mentioned, if you use Apple LLVM Compiler 4.0 + (which comes with xCode 4.4+, I think) there is a neat way to do what you require, with no boilerplate code at all, using literals.

Here's how you would do it:

for (id key in [stats allKeys]) {
    for (Food * food in stats[key]) {

        //this is the object you're looking for
        NSLog(@"Object: %@", food);

    }
}

Where stats is your dictionary object that has an array for each of its keys. Updating to LLVM 4.0 worths the effort for this only :)

If you choose to enumerate each array using an iterator, you can even access the object like this:

stats[key][i]

Rad'Val
  • 8,895
  • 9
  • 62
  • 92
  • The methods required for this to work are only available in >= iOS 6. – Paul.s Nov 30 '12 at 22:24
  • has nothing to do with the iOS, it's the compiler – Rad'Val Nov 30 '12 at 22:25
  • @Paul.s No, that code will work back to iOS 5.0. I use that syntax in one of my apps and it works just fine under 5.0 through 6.x. – rmaddy Nov 30 '12 at 22:25
  • As I said, above, if you have LLVM 4.0+ you can compile projects written for any version of iOS, even older than 5 – Rad'Val Nov 30 '12 at 22:27
  • For example NSDictionary uses the method [objectForKeyedSubscript](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html#//apple_ref/doc/uid/20000140-DontLinkElementID_4), which was added in iOS 6 – Paul.s Nov 30 '12 at 22:27
  • See this question http://stackoverflow.com/questions/11694877/is-there-any-way-to-get-the-neat-objective-c-literal-indexing-feature-in-xcode-4 – Rad'Val Nov 30 '12 at 22:33
  • Pretty much, although, you still need to add the category interface for older projects. – Rad'Val Nov 30 '12 at 22:40
0

A slightly more efficient way of enumerating a dictionary

[stats enumerateKeysAndObjectsUsingBlock:^(NSString *category, NSArray *foodItems, BOOL *stop) {
  for (Food *food in foodItems) {
    // do something with food
  }
}];

Obviously if you needed the dictionary to be iterated in the same order each time you'll need to use something a little longer

NSArray *sortedKeys = [[stats allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];

for (id key in sortedKeys) {
  NSArray *foodArray = [stats objectForKey:key];
  for (Food *food in foodArray) {
    // do stuff with Food object
  }
}
Paul.s
  • 38,494
  • 5
  • 70
  • 88