Reputation: 2095
I've got the following NSArray :
NSArray myArray = @[@{@300:@"5 min"},
@{@900:@"15 min"},
@{@1800:@"30 min"},
@{@3600:@"1 hour"}];
I want the list of value of my dictionaries :
@[@"5 min",@"15 min",@"30 min",@"1 hour"]
And the list of key of my dictionaries :
@[@300, @900, @1800, @3600]
What is the best way to do that ? I was thinking about predicate, but I don't know how to use it ?
Upvotes: 4
Views: 6480
Reputation: 18253
Without some code to show how you'd want to go about this it is difficult to be sure exactly what you are after, and there is a bit of confusion in the question.
First, a predicate is exactly that - a statement that can be proven true or false. Predicates are hence used in logic expressions, including those employed implicitly in database queries - such as Core Data.
That is not what you want, if I read your question correctly. What you want is to reduce the complexity of your data model, removing some excess (one would hope) information in the process. A sort of flattening of an array of dictionaries.
Fair enough.
I can also see how the confusion with predicates came about - they are most often constructed using Key-Value Coding. KVC, as it is also known, is a very powerful technique that can accomplish what you are after. It just does not have much to do with a logic statement.
Having cleared that up, with KVC you can do what you want, and with minimal fuss. It goes like this:
NSArray *values = [myArray valueForKeyPath: @"@unionOfArrays.@allValues"];
NSArray *keys = [myArray valueForKeyPath: @"@unionOfArrays.@allKeys"];
A brief explanation might be in order:
The results that we want are
To obtain all values (or keys) from a dictionary using KVC, the special key is @allValues
or @allKeys
, respectively.
The @unionOfArrays
operator makes a union of the arrays obtained from the expression that follows it, i.e., flattens it into the array you wanted.
The price you pay for this coding simplicity is that you have to use KVC key paths with collection operators, which are just strings in your code. You therefore lose any help from the compiler with syntax and it doesn't check that the keys you enter exist in the objects. Similarly, the debugger and error messages are unhelpful if you mistype or use the wrong operator, for instance.
Upvotes: 9
Reputation: 130193
@johnyu's answers is technically correct, but I don't see any reason to include the secondary loop, especially if the data structure will remain the same.
NSArray *myArray = @[@{@300:@"5 min"},
@{@900:@"15 min"},
@{@1800:@"30 min"},
@{@3600:@"1 hour"}];
NSMutableArray *arrayOfValues = [NSMutableArray new];
NSMutableArray *arrayOfKeys = [NSMutableArray new];
for (NSDictionary *dictionary in myArray) {
[arrayOfValues addObject:dictionary.allValues[0]];
[arrayOfKeys addObject:dictionary.allKeys[0]];
}
NSLog(@"%@",arrayOfKeys);
NSLog(@"%@",arrayOfValues);
Upvotes: 1
Reputation: 2151
Try this:
NSArray *myArray = @[@{@300:@"5 min"},
@{@900:@"15 min"},
@{@1800:@"30 min"},
@{@3600:@"1 hour"}];
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
NSMutableArray *valueArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in myArray) {
for (NSString *key in dictionary) {
[keyArray addObject:key];
[valueArray addObject:[dictionary objectForKey:key]];
}
}
Upvotes: 0
Reputation: 722
You can use dictionary property allValues to get all values of dictionary.
Try this code in your case
NSArray *myArray = @[@{@300:@"5 min"},
@{@900:@"15 min"},
@{@1800:@"30 min"},
@{@3600:@"1 hour"}];
NSMutableArray *arr = [NSMutableArray array];
for (NSDictionary *dict in myArray) {
[arr addObject:[[dict allValues] objectAtIndex:0]];
}
NSLog(@"%@",arr);
Note : Make sure you have only one value in each dictionary. it will return
[
5 min,
15 min,
30 min,
1 hour
]
Upvotes: 1