This question already has answers here:
sort NSDictionary values by key alphabetical order
(4 answers)
Closed 6 years ago.
I have a dictionary in which, for a single key(for example key "0") there are a key value pair data.The keys are like name, id,p_id. I want to sort the NSMutableDictionary for the values related to the Key "name". The data in the dictionary is as follows,
0 = {
id = 12;
name = "Accounts ";
"p_id" = 13222071;
};
1 = {
id = 13;
name = "consultant";
"p_id" = 15121211;
};
2 = {
id = 11;
name = "Tania";
"p_id" = 10215921;
};
}
Any help is appreciated!
Please try out the below code:
[yourMutableArray sortUsingComparator: (NSComparator)^(NSDictionary *a, NSDictionary *b) {
NSString *key1 = [a objectForKey: #"name"];
NSString *key2 = [b objectForKey: #"name"];
return [key1 compare: key2];
}];
NSLog(#"Sorted Array By name key : %#", yourMutableArray);
Hope this helps!
NSArray *sortedKeys = [dict.allKeys sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *d1, NSDictionary *d2) {
return [d1[#"name"] compare:d2[#"name"]];
}];
NSArray *objects = [dict objectsForKeys:sortedKeys notFoundMarker:[NSNull null]];
Dictionaries are not sorted, and doesn't resemble any order. What you should do is to getAll the keys first. Then apply a sort method on the keys, then request the objects according to the ordered keys.
E.g:
NSArray *keys = [dictionary allKeys];
NSArray *sortedKeys = <sort the keys according to your preferred method>
Now you can iterate the Dictionary from the order of the array sortedKeys.
While it has been made abundantly clear that Dictionaries can't be sorted and rightfully so, that does not mean the ends you are aiming for can't be achieved. This code will do that for you:
NSArray *arrayOfDicts = dic.allValues; //Now we got all the values. Each value itself is a dictionary so what we get here is an array of dictionaries
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES]; //Create sort descriptor for key name
NSArray *sortingDesc = [NSArray arrayWithObject:nameDescriptor];
NSArray *sortedArray = [arrayOfDicts sortedArrayUsingDescriptors:sortingDesc]; //Get sorted array based on name
NSMutableDictionary *kindaSortedDict = [[NSMutableDictionary alloc] init];
int keyForDict=0;
for(NSDictionary *valDict in sortedArray)
{
[kindaSortedDict setObject:valDict forKey:[NSString stringWithFormat:#"%i",keyForDict]]; //Set values to our new dic which will be kind of sorted as the keys will be assigned to right objects
keyForDict++;
}
//Now you can simply get sorted array of keys from kindaSortedDic and results for them will always be sorted alphabetically. Alternatively you can just skip all that bother and directly use sortedArray
I have added comments in code to help you understand that.
For accessing sorted values I'd do this:
NSArray *sortedKeys = [kindaSortedDict.allKeys sortedArrayUsingDescriptors:
#[[NSSortDescriptor sortDescriptorWithKey:#"intValue"
ascending:YES]]];
for(NSString *key in sortedKeys)
{
NSDictionary *valDict = [kindaSortedDict objectForKey: key];
NSLog(#"Dict is: %# for key: %#",valDict,key);
}
Related
I have a simple UITableView, when users adds new rows, these will be added to the NSMutableDictionary. I can retrieve the values for a specific key.
NSArray *myArr = [myDictionary valueForKey:#"Food"];
This will show me all values for key food, this is an example of my NSLog:
(
burger,
pasta )
If I add more objects to myDictionary but for a different key, for example:
NSArray *drinks = [NSArray arrayWithObjects:#"cola",#"sprite",nil];
[myDictionary setObject:drinks forKey:#"Drink"];
I can't retrieve all values using the following code:
NSArray *allMenu = [myDictionary allValues];
It shows me the following NSLog:
(
(
burger,
past
),
(
cola,
sprite
) )
I don't know where is the problem. Why I can't get all values from NSDictionary to NSArray.
If I use the code:
NSArray *allMenu = [[myDictionary allValues] objectAtIndex:0];
will show me the Food values. If I change objectAtIndex to 1 will show me the Drink value.
I am not entirely sure what you are asking, if you are trying to print all of the values within an NSDictionary do the following:
//Gets an array of all keys within the dictionary
NSArray dictionaryKeys = [myDictionary allKeys];
for (NSString *key in dictionaryKeys)
{
//Prints this key
NSLog(#"Key = %#", key);
//Loops through the values for the aforementioned key
for (NSString *value in [myDictionary valueForKey:key])
{
//Prints individual values out of the NSArray for the key
NSLog(#"Value = %#", value);
}
}
You can do this in one line by flattening the returned 2-dimensional array by using key value coding (KVC). I found this in another answer, see the docs. In your case, it looks as follows:
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionary];
NSArray *food = [NSArray arrayWithObjects:#"burger",#"pasta",nil];
[myDictionary setObject:food forKey:#"Food"];
NSArray *drinks = [NSArray arrayWithObjects:#"cola",#"sprite",nil];
[myDictionary setObject:drinks forKey:#"Drink"];
NSArray *allMenue = [[myDictionary allValues] valueForKeyPath:#"#unionOfArrays.self"];
Try this Solution :
- (NSDictionary *) indexKeyedDictionaryFromArray:(NSArray *)array
{
id objectInstance;
NSUInteger indexKey = 0U;
for (objectInstance in myArr)
[mutableDictionary setObject:objectInstance forKey:[NSNumber numberWithUnsignedInt:indexKey++]];
return (NSDictionary *)[myDictionary autorelease];
}
I have an array having objects with different properties. I want to create an array of sets which contain objects with same value of a single property of the object.
Suppose this is an array of object which has property a and b
1: {a:10, b:5}, 2: {a:2,b:5}, 3: {a:20,b:5}, 4: {a:5,b:5}, 5: {a:4,b:20}, 6: {a:51,b:20}
I want to create another array of NSSet of objects with distinct values of property b
so the result would be the following Array of 2 NSSet
1: {a:10, b:5}, {a:2,b:5}, {a:20,b:5}, {a:5,b:5}
2: {a:4,b:20}, {a:51,b:20}
How can this be done?
I'd do this by first creating a dictionary of sets where the keys of the dictionary are the unique values of "b".
Note: This is untested code. There could be typos here.
NSArray *objectArray = ... // The array of "SomeObject" with the "a" and "b" values;
NSMutableDictionary *data = [NSMutableDictionary dictionary];
for (SomeObject *object in objectArray) {
id b = object.b;
NSMutableSet *bSet = data[b];
if (!bSet) {
bSet = [NSMutableSet set];
data[b] = bSet;
}
[bSet addObject:object];
}
NSArray *setArray = [data allValues];
setArray will contain your array of sets.
This codes also assumes you have a sane isEqual: and hash implementation on your SomeObject class.
This is how you can do this:
NSArray *data = #[#{#"a":#10, #"b":#5}, #{#"a":#2,#"b":#5}, #{#"a":#4,#"b":#20}, #{#"a":#51,#"b":#20}];
NSSet *bSet = [NSSet setWithArray: [data valueForKey: #"b"]];
NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity: bSet.count];
for (NSNumber *bValue in bSet) {
NSPredicate *anArrayFilterPredicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *aDictionaryData, NSDictionary *bindings) {
if ([aDictionaryData[#"b"] isEqual:bValue]) {
return YES;
}
return NO;
}];
NSArray *uniqueBValueArray = [data filteredArrayUsingPredicate:anArrayFilterPredicate];
[filteredArray addObject:uniqueBValueArray];
}
NSLog(#"filteredArray = %#", filteredArray);
Using Key-Value coding collection operators, we can get the array of distinct values for an object. Then you could easily compute the results you want.
In your case this could be done like this.
NSArray *arrayOfDistinctObjects = [array valueForKeyPath:#"#distinctUnionOfObjects.b"];
NSMutableArray *newSetArray = [NSMutableArray new];
for (id value in arrayOfDistinctObjects) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.b == %#", value];
NSArray *filterArray = [array filteredArrayUsingPredicate:predicate];
NSSet *newSet = [NSSet setWithArray:filterArray];
[newSetArray addObject:newSet];
}
where array is the array of objects on which you wanna operate.
arrayOfDistinctObjects gives you the array of distinct values for b.
I have a dictionary which contain this data:
(
contact={name="Lion",id="1",photo="simba.png",address="elm street"},
{name="Cat",id="2",photo="halleberry.png",address="attic"},
{name="Bat",id="3",photo="dracule.jpg",address="long way home baby"}
)
From that NSDictionary, i grab only the name and sorted it alphabetically. Like this:
(B={"Bat"}, C={"Cat"}, L={"Lion"})
This is the code i used:
NSMutableDictionary* sortedDict = [NSMutableDictionary dictionary];
for (NSDictionary* animal in dataDict[#"user"]){
NSString* name = animal[#"name"];
if (![name length])
continue;
NSRange range = [name rangeOfComposedCharacterSequenceAtIndex:0];
NSString* key = [[name substringWithRange:range] uppercaseString];
NSMutableArray* list = sortedDict[key];
if (!list){
list = [NSMutableArray array];
[sortedDict setObject:list forKey:key];
}
[list addObject:name];
Then, what i want to ask is. What i need to create an array of photos but sorted alphabetically based on the name. I mean something like this:
(B="dracule.jpg", C="halleberry.png"...etc)
I also heard that this will be more effective to use (B={name="Bat", photo="draggle.jpg"}) but don't know how i can make something like this and don't know how to call it separately. Please i need your help :"(
You can easily sort the array which contains dictionaries values, see below
//Get the contact array.
NSArray *contacts=[dic objectForKey:#"contact"];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortedArray = [contacts sortedArrayUsingDescriptors:#[sortDescriptor]];
I hope it helps.
I have array which has dictionaries. each dictionary is :
NSDictionary *imageAndIndex=[[NSDictionary alloc] initWithObjectsAndKeys:image,[NSNumber numberWithLong:index], nil];
Where the object is image, and the key is NSNumber key made from index.
I want to sort the array according to the NSNumbers indexes so it will become:
0,1,2,3,4 ..
How can i use NSSortDescriptor ?
The problem (and the debate herein) is complicated by two factors: 1) The OP design choice to sort based on a dictionary key, rather than on a value. #sooper in comments pointed out correctly that the better design would be to add a #"sortBy" key, whose value is the NSNumber to be sorted. 2) The second complication is the question's reference to NSSortDescriptor, which is going to depend upon values for a given key, not the key itself.
I think the right answer is to take the #sooper suggestion to add #"sortBy" key-value pairs, but if you must sort the data as is...
- (void)sortDictionaries {
NSDictionary *d0 = #{ #0: someUIImage0};
NSDictionary *d1 = #{ #1: someUIImage1};
NSDictionary *d2 = #{ #": someUIImage2};
NSArray *unsorted = #[d1, d2, d0];
NSArray *sorted = [unsorted sortedArrayUsingComparator:^(NSDictionary *obj1, NSDictionary *obj2) {
NSNumber *key1 = [self numericKeyIn:obj1];
NSNumber *key2 = [self numericKeyIn:obj2];
return [key1 compare:key2];
}];
NSLog(#"%#", sorted);
}
- (NSNumber *)numericKeyIn:(NSDictionary *)d {
// ps. yuck. what do we want to assume here?
// that it's a dictionary?
// that it has only one key value pair?
// that an NSNumber is always one of the keys?
return [d allKeys][0];
}
Not sure why we had to handle this with so much ill-temperment. It's programming, it's supposed to be fun!
Anyway, here's how you'd do it with a sort key and sort descriptor:
- (void)betterSortDictionaries {
NSDictionary *d0 = #{ #"image":image1, #"sortBy":#0 };
NSDictionary *d1 = #{ #"image":image2, #"sortBy":#1 };
NSDictionary *d2 = #{ #"image":image3, #"sortBy":#2 };
NSArray *unsorted = #[d1, d2, d0];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"sortBy" ascending:YES];
NSArray *sorted = [unsorted sortedArrayUsingDescriptors:#[descriptor]];
NSLog(#"%#", sorted);
}
I have nsdictionary which contains elements with following structure
name --> value
email--> key
I get value(of above structure) from user,
now I want to search element in nsdictionary by value(entered by user) not by key, whether it is present in nsdictionary or not and also want to get index of that element if present.
How to do this?
The best to do so would propably be
- (NSArray *)allKeysForObject:(id)anObject
This method of NSDictionary gives you back all the keys having anObject as their value. If you only have each object once in the whole dictionary it will logically return an array with only one key in it.
NSArray * users = ...; //your array of NSDictionary objects
NSPredicate *filter = [NSPredicate predicateWithFormat:#"email = test#gmail.com"];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:filter];
for more than one value of email, then use an OR in the predicate:
filter = [NSPredicate predicateWithFormat:#"contact_type = 42 OR contact_type = 23"];
The dictionary data structure has no 'order', so you'd have to search for your key by iterating the collection and looking for the desired value.
Example:
NSString *targetKey = nil;
NSArray *allKeys = [collection allKeys];
for (int i = 0; i < [allKeys count]; ++i) {
NSString *key = [allKeys objectAtIndex:i];
NSString *obj = [collection objectForKey:key];
if ([obj isEqualToString:searchedString]) { // searchedString is what you're looking for
targetKey = key;
break;
}
}
// check if key was found (not nil) & proceed
// ...
You can search the entered value in NSDictionary , but you can't get an index of value , as NSDictionary has no order of key value pair.
NSArray *array = [yourDictionaryObject allValues];
if ([array containsObject:#"userEnteredValue"]) {
<#statements#>
}
You need to iterate through the Dictionary for the keys has the Value of your need:
Try this:
NSArray *keys= [json allKeys];
for (NSString *keysV in keys){
NSLog(#"Keys are %#", keysV);
if([Your_Dict objectForKey: keysV] isEqual:#"string to Match"){
//Do your stuff here
}
}