views:

44

answers:

2

I have an NSDictionary with NSStrings

Some of the valueForKey:@"Key" have no entry so it's (null)

NSMutableString* addressDictionaryToString = [NSMutableString string];  // use mutable string!
for (NSDictionary* item in address) {     // use fast enumeration!
        [addressDictionaryToString appendFormat:@"%@, %@, %@, %@",
         [item objectForKey:@"Street"],         
         [item objectForKey:@"City"],
         [item objectForKey:@"State"],
         [item objectForKey:@"ZIP"]
         ];
    NSLog(@"MutableString: %@", addressDictionaryToString);
}

So I want to build an NSMutableString but filter out those keys that are null. Any ideas?

UPDATE:::::

Basically I want my resulting String to look like

1 Infinite Loop, Cupertino, CA, 95014 (IF all fields are available)

If Im missing the Street then

Cupertino, CA, 95014

If I'm missing the State then

1 Infinite Loop, Cupertino, 95014

If I only have the state then it should print

CA

(notice that there are no commas on the last element)

+1  A: 

How about checking if there's a value for the key?

NSMutableString * addressDictionaryToString = [NSMutableString string];
for (NSDictionary * item in address)
{
    if ([item objectForKey:@"Street"])
        [addressDictionaryToString appendFormat:@"%@, ", 
         [item objectForKey:@"Street"]];
    if ([item objectForKey:@"City"])
        [addressDictionaryToString appendFormat:@"%@, ", 
         [item objectForKey:@"City"]];
    if ([item objectForKey:@"State"])
        [addressDictionaryToString appendFormat:@"%@, ", 
         [item objectForKey:@"State"]];
    if ([item objectForKey:@"ZIP"])
        [addressDictionaryToString appendFormat:@"%@, ", 
         [item objectForKey:@"ZIP"]];
    NSLog(@"MutableString: %@", addressDictionaryToString);
}

The thing is, in your last question, you said your goal was to create a CSV file. It's not technically valid CSV if your rows have varying numbers of fields with no reliable way to identify each one.

Instead, you might try this:

NSMutableString * addressDictionaryToString = [NSMutableString string];
for (NSDictionary * item in address)
{
    [addressDictionaryToString appendFormat:@"%@,", 
     ([item objectForKey:@"Street"]) ? [item objectForKey:@"Street"] : @"" ];
    // ...
    NSLog(@"MutableString: %@", addressDictionaryToString);
}

It checks for the presence of a value and inserts that value if there is one, or just an empty string (resulting in "value,value,,value..."). Also remember there shouldn't be a space after the comma, so I've removed that from this example.

Joshua Nozzi
Thanks Joshua!I had another method to remove whitespace and replace " " with %20's for geocoding
Cocoa Dev
Don't neglect your accept rate. 56% doesn't encourage people to keep answering your questions ...
Joshua Nozzi
whats an accept rate?
Cocoa Dev
:-) It's the % of questions you asked for which you accepted answers (thereby giving more karma points to the answerers). It motivates people to answer more of your questions. A closer look does show that some of your questions remain unanswered, though, so not your fault. :-)
Joshua Nozzi
when you run the code[addressDictionaryToString appendFormat:@"%@,", ([item objectForKey:@"Street"]) ? [item objectForKey:@"Street"] : @"" ];does the formatted string get saved into the addressDictionaryToString NSMutableString?
Cocoa Dev
Yes. The very beginning of the line shows this. You're appending a format. When it comes time to provide the value for the %@ placeholder, you're using a C ternary operator ( http://en.wikipedia.org/wiki/Conditional_operator ) to substitute either a value if one is present or an empty string if not.
Joshua Nozzi
Thanks JoshuaI dont want to sound like an idiot but can I string multiple operators together?[addressDictionaryToString appendFormat:@"%@, %@, %@, %@", ([item objectForKey:@"Street"]) ? [item objectForKey:@"Street"] : @"", ([item objectForKey:@"City"]) ? [item objectForKey:@"City"] : @"", ([item objectForKey:@"State"]) ? [item objectForKey:@"State"] : @"", ([item objectForKey:@"ZIP"]) ? [item objectForKey:@"ZIP"] : @"" ];
Cocoa Dev
Sure, but the code starts to become difficult to read. See where I have the commented "// ..."? I meant that there, you can copy the above line and just change the keys. This makes it easier to add new fields/keys by copying the line and it makes it far easier to read and step through in the debugger.
Joshua Nozzi
... also, imagine if you miss a comma, bracket, or other silly thing somewhere in that tangled mess. Just getting it to compile might hurt. :-)
Joshua Nozzi
orangecl4now: Don't accept answers just to raise your accept rate. Accept answers that you have determined to be correct. I explain here: http://boredzo.org/blog/archives/2010-03-13/the-green-checkmark-of-acceptance
Peter Hosey
Joshua Nozzi, orangecl4now: The code in the answer will include an extra “, ”. Better to add the elements to a mutable array and send the array a `componentsJoinedByString:` message. http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/componentsJoinedByString: orangecl4now: The alternate code you provide in each of your comments will add to the string unconditionally; whether it adds a value from the dictionary or an empty string, it will follow that with “, ”. Expect to see “, , ” in your output.
Peter Hosey
A: 

Not exactly sure what you're trying to do but this:

NSDictionary *d=[NSDictionary dictionaryWithObject:[NSNull null] forKey:@"ns"];
NSString *n=[@"Steve " stringByAppendingFormat:@"%@",[d objectForKey:@"ns"]];
NSLog(@"%@",n);

... prints:

Steve <null>

If the key itself does not exist then it will throw an exception when you try to get the value for the nonexistent key. The only recourse in this instance is to check for the key in each dictionary before trying to use it to retrieve a value.

TechZen