Get a list of Keys from NSDictionary containing NSNumber bools where the value is #YES - objective-c

I'm trying to get an array of keys where the value for the corresponding key in an NSDictionary is #YES.
For EG,:
Starting Dictionary:
NSDictionary* dict = #{#"key1" : #YES, #"key2": #YES, #"key3": #NO, #"key4": #NO};
Desired Result:
NSArray* array = #[#"key1", #"key2"];
I tried doing this with NSPredicates and subpredicates but couldn't find one that did what i wanted. My "working" but ugly solution is:
NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:0];
NSDictionary* dict = #{#"key1" : #YES, #"key2": #YES, #"key3": #NO, #"key4": #NO};
for (NSString* key in [dict allKeys]) {
if ([[dict objectForKey:key] isEqualToNumber:#YES])
[array addObject:key];
}
What is a better way of doing this, possibly with NSPredicates?.

This kind of abstracts a lot of the messiness away
NSArray *results = [dict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
return [obj isEqualToNumber:#YES];
}].allObjects;
NSLog(#"%#", results);

Related

How to detect if the NSDictionary item is an integer?

I have a NSDictionary object with 2 items, the first one is a NSString and the second is an Integer. When I loop into the dictionary items I'd like detect what of they is an Integer.
What is the best way to do it?
The current dictionary is:
[[NSDictionary alloc] initWithObjectsAndKeys:#"San", #"name", #"123", #"id", nil]
The item you are putting in the dictionary is in no way an integer, it's a NSString which only contains numbers. Why not just use a NSNumber object and use it the way it should be?
[[NSDictionary alloc] initWithObjectsAndKeys:#"San", #"name", #123, #"id", nil]
This uses a literal for a NSNumber.
You can use isKindOfClass: to check if an object is of a specific class and enumerateKeysAndObjectsUsingBlock: to analyze every object contained in a dictionary.
For example:
NSDictionary *dictionary = #{#"name": #"San", #"id": #123};
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSNumber class]])
NSLog(#"%#: %# is a number", key, obj);
else
NSLog(#"%#: %# is NOT a number", key, obj);
}];
The first line is a NSDictionary creation using literals, the same is for #123, which automatically insert a NSNumber with 123 value in the dictionary.

Objective-C: Sort keys of NSDictionary based on dictionary entries

OK so I know that dictionaries can't be sorted. But, say I have NSMutableArray *keys = [someDictionary allKeys]; Now, I want to sort those keys, based on the corresponding values in the dictionary (alphabetically). So if the dictionary contains key=someString, then I want to sort keys based on the strings they correspond to. I think its some application of sortUsingComparator but its a little out of my reach at this point.
NSArray *keys = [someDictionary allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [someDictionary objectForKey:a];
NSString *second = [someDictionary objectForKey:b];
return [first compare:second];
}];
NSDictionary *dict = // however you obtain the dictionary
NSMutableArray *sortedKeys = [NSMutableArray array];
NSArray *objs = [dict allValues];
NSArray *sortedObjs = [objs sortedArrayUsingSelector:#selector(compare:)];
for (NSString *s in sortedObjs)
[sortedKeys addObjectsFromArray:[dict allKeysForObject:s]];
Now sortedKey will contain the keys sorted by their corresponding objects.
Sort keys of NSDictionary based on dictionary keys
Abobe is for returning a sorted array with based on dictionary content, this is for returning an array sorted by dictionary key:
NSArray *keys = [theDictionary allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
return [a compare:b];
}];
NSMutableArray *sortedValues = [NSMutableArray new];
for(NSString *key in sortedKeys)
[sortedValues addObject:[dictFilterValues objectForKey:key]];
Just write it here cause I didn't find it anywhere: To get an alphanumeric sorted NSDictionary back from an NSDictionary based on the value - which in my case was neccessary - you can do the following:
//sort typeDict alphanumeric to show it in order of values
NSArray *keys = [typeDict allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [typeDict objectForKey:a];
NSString *second = [typeDict objectForKey:b];
return [first compare:second];
}];
NSLog(#"sorted Array: %#", sortedKeys);
NSMutableDictionary *sortedTypeDict = [NSMutableDictionary dictionary];
int counter = 0;
for(int i=0; i < [typeDict count]; i++){
NSString *val = [typeDict objectForKey:[sortedKeys objectAtIndex:counter]];
NSString *thekey = [sortedKeys objectAtIndex:counter];
[sortedTypeDict setObject:val forKey:thekey];
counter++;
}
NSLog(#"\n\nsorted dict: %#", sortedTypeDict);
Not a big deal!
If any value from the dictionary is null then use this code
NSArray *keys = [typeDict allKeys];
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES];
NSArray *sortedKeys = [keys sortedArrayUsingDescriptors:#[sd]];
NSLog(#"SORT 1 %#",sortedKeys);
NSMutableDictionary *sortedTypeDict = [NSMutableDictionary dictionary];
int counter = 0;
for(int i=0; i < [typeDict count]; i++){
id val = [typeDict objectForKey:[sortedKeys objectAtIndex:counter]];
NSString *thekey = [sortedKeys objectAtIndex:counter];
[sortedTypeDict setObject:val forKey:thekey];
counter++;
}
NSLog(#"\n\nsorted dict: %#", sortedTypeDict);

Creating NSDictionary with keys that have multiple values

I have a mutable array that contains NSDictionary dic1 objects,
each dictionary has a key called contactId, more than one dictionary can have the same value for contactId.
What I want to do is to create an NSDictionary with unique contactIds as the keys and an array value that contains a list of all NSDictionary dic1 objects that have the value contactId equal to the key.
How can I do this?
My data looks like this:
**myArray**:[ **dic1** {contactId = x1 , name = name1 }, **dic2**{contactId = x2, name =
name2 }, **dic3**{contactId = x1, name = name3} ]
I want it to become like this:
**NSDictionary**: { **x1**:[dic1, dic3], **x2**:[dic2] }
Use fast enumeration:
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (id obj in myArray)
{
NSString *contactId = [obj objectForKey:#"contactId"];
NSMutableSet *contacts = [result objectForKey:contactId];
if (!contacts)
{
contacts = [NSMutableSet set]
[result setObject:contacts forKey:contactId];
}
[contacts addObject:obj];
}
You could use blocks for no real added benefit:
__block NSMutableDictionary *result = [NSMutableDictionary dictionary];
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
NSString *contactId = [obj objectForKey:#"contactId"];
NSMutableSet *contacts = [result objectForKey:contactId];
if (!contacts)
{
contacts = [NSMutableSet set]
[result setObject:contacts forKey:contactId];
}
[contacts addObject:obj];
}];
How about the classic way?
NSMutableDictionary* Result;
NSEnumerator* Enumerator;
NSDictionary* Dict;
Result=[[NSMutableDictionary alloc] init];
Enumerator=[YourArray objectEnumerator];
while ((Dict=[Enumerator nextObject])!=nil)
{
NSString* ContactID;
NSMutableSet* Contacts;
ContactID=[Dict objectForKey:#"contactID"];
Contacts=[Result objectForKey:ContactID];
if (Contacts==nil)
{
Contacts=[[NSMutableSet alloc] init];
[Result setObject:Contacts forKey:ContactID];
[Contacts release];
}
[Contacts addObject:Dict];
}
This should create a Result dictionary. I haven't tested (or even compiled) this, though.

all Keys and Objects from a NSDictionary to a NSString

I've got a NSDictionary and I'd like put all of it's objects and keys into a NSString, so that I can finally display them in a label like this:
key1: object1
key2: object2
key3: object3
... ...
Any ideas?
Build the string and then set it to the labels text.
NSMutableString *myString = [[NSMutableString alloc] init];
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[myString appendFormat:#"%# : %#\n", key, obj];
}];
self.label.text = myString;
Note
The docs (String Programming Guide) for the %# format specifier state:
%#
Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function.
So if these are your own custom objects in the dictionary you will most likely need to override the description method to provide more meaningful output
Update
You mention that you need your output sorted by keys - dictionaries are not ordered so you will have to do it differently - this example assumes that your keys are strings
NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSMutableString *myString = [[NSMutableString alloc] init];
for (NSString *key in sortedKeys) {
[myString appendFormat:#"%# : %#\n", key, [dictionary objectForKey:key]];
}
self.label.text = myString;
try this
for(id key in [dictionary allKeys])
{
id value = [dictionary objectForKey:key];
NSLog(#"%# : %#", key, value);
}
NSString *row;
for (id key in dictionary) {
row = [NSString stringWithFormat:"%#: %#", key, [dictionary objectForKey:key]];
// do something with your row string
}
Iam trying to append two time values from my TCTime object and display in label, even though I added "\n" towards the end it is printing only the first value but not the second value.
_feedTimes is NSArray.
NSMutableString *myString = [[NSMutableString alloc] init];
TCTime *time = _feedTimes[indexPath.row];
[myString appendFormat:#"%s : %#\n", "Time 1 ", time.Time1];
[myString appendFormat:#"%s : %#\n", "Time 2 ", time.Time2];
self.label.text = myString;

how to create a NSDictionary consisting of NSArray of NString for key and bunch of int for the value?

here is the problem :
NSArray * alphabets = [NSArray arrayWithObjects:#"a",#"b",#"c",#"d",#"e",#"f",#"g",#"h",#"i",#"j",#"k",#"l",#"m",#"n",#"o",#"p",#"q",#"r",#"s",#"t",#"u",#"v",#"w",#"x",#"y",#"z",nil];
NSDictionary * alphaToNum = [NSDictionary dictionaryWithObject:alphabets forKey:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26];
//I know above line meant to not work I just brought it here as an example
how can I create a dictionary just like above which is working?
You can only use objects as keys or values in a NSDictionary, so you have to use NSNumber as wrapper for your integer key.
NSMutableDictionary *alphaToNum = [NSMutableDictionary dictionary];
NSArray *alphabet = [NSArray arrayWithObjects:#"a",#"b",#"c",#"d",#"e",#"f",#"g",#"h",#"i",#"j",#"k",#"l",#"m",#"n",#"o",#"p",#"q",#"r",#"s",#"t",#"u",#"v",#"w",#"x",#"y",#"z",nil];
NSInteger index = 0;
for(NSString *character in alphabet)
{
index ++;
[alphaToNum setObject:character forKey:[NSNumber numberWithInteger:index]];
}