Search NSArray of NSDictionaries - iphone

I have an array with dictionaries,
and need to search trough the array
and modify a specific dictionary in the array found by an object name inside the dictionary.
So , create the mutable array, dictionary , and add many dictionaries to the array
...{ self.bloquesArray = [[[NSMutableArray alloc] init]autorelease];
[self createBloqueDicto];
[self.unBloqueDicto setObject:#"easySprite" forKey:#"Name"];
[self.unBloqueDicto setObject:#"290" forKey:#"X"];
[self.unBloqueDicto setObject:#"300" forKey:#"Y"];
[self.bloquesArray addObject:self.unBloqueDicto];
}
- (void)createBloqueDicto {
self.unBloqueDicto = [[[NSMutableDictionary alloc] init] autorelease];
}
so now I need to change the value for the key X and Y in the dictionary with
key: Name = easySprite
so need to find that specific dictionary [other dictionaries have different values for Name]
how can I do this please?
thanks!

Do the following to get the matched dictionaries,
NSPredicate *p = [NSPredicate predicateWithFormat:#"Name = %#", #"easySprite"];
NSArray *matchedDicts = [bloquesArray filteredArrayUsingPredicate:p];
Now the matchedDicts contains the dictionaries with the value #"easySprite" for the key #"Name". Do the rest(changing the X and Y) from there.

Related

Sorting Multiple NSMutableArray's

I have 3 MutableArray's Named:
tvShows
tvNetworks
tvdbID
I need to sort them by the name of the tvShows.
But the need to stay linked.
So e.g.:
tvShows = Breaking Bad, House, Community;
tvNetworks = AMC, FOX, NBC;
tvdbID = 81189, 73255, 94571;
Needs To Become:
tvShows = Breaking Bad, Community, House;
tvNetworks = AMC, NBC, FOX;
tvdbID = 81189, 94571, 73255;
How would I do this? It's my first app so sorry if it's a realy easy question.
store them in an array of dictionaries then sort with an NSArray sort function: (below)
NSDictionary * dict1 = #{#"title":#"breaking bad",#"network":#"AMC",#"tvbdID":#(81189)};
NSDictionary * dict2 = #{#"title":#"house",#"network":#"FOX",#"tvbdID":#(73255)};
NSDictionary * dict3 = #{#"title":#"Community",#"network":#"NBC",#"tvbdID":#(94571)};
NSArray * array = #[dict1,dict2,dict3];
NSSortDescriptor * desc = [NSSortDescriptor sortDescriptorWithKey:#"title"ascending:YES selector:#selector(caseInsensitiveCompare:)];
NSArray * sortedArray = [array sortedArrayUsingDescriptors:#[desc]];
I would personally create a custom NSObject called TVShow, that has properties of showName, network, and tvbdID. This way, you only have one array of each show. Assuming your array is called myShows, you could do something like this:
[allShows sortUsingComparitor:^NSComparisonResult(id a, id b) {
NSString *firstName = [(TVShow*)a showName];
NSString *secondName = [(TVShow*)b showName];
return [firstName compare: secondName];
}];
That is, if you wanted to sort by show name. You can swap network for showName if you wanted to sort by network!
No idea what your end goal is, but you should probably create a TVShow class that has properties (i.e., instance variables) for "title," "network", and "dbid." Then you can instantiate three TVShow objects with their appropriate properties, put them in a mutable array, and use one of the sorting methods on NSMutableArray -- I'd probably choose sortUsingComparator:.
you can't do it with 3 independent arrays but maybe with 1 dictionary where the keys are tv shows and the value is a dictionary with 2 keys: tvNetworks & tvdbIDs
sample:
NSDictionary *data = #{#"Breaking Bad":#{#"tv" : #"AMC", #"tvdb": #(81189)},
#"House":#{#"tv" : #"FOX", #"tvdb": #(73255)},
#"Community":#{#"tv" : #"NBC", #"tvdb": #(94571)}};
NSArray *sortedShows = [data.allKeys sortedArrayUsingSelector:#selector(compare:)];
for (id show in sortedShows) {
NSLog(#"%# = %#", show, data[show]);
}
One of the easiest and most straightforward ways to do this would be to create one array of dictionaries, like this:
NSMutableArray *tvShowInfos = [NSMutableArray array];
for (NSInteger i = 0; i < tvShows.count; i++) {
NSDictionary *info = #{#"show": [tvShows objectAtIndex:i],
#"network": [tvNetworks objectAtIndex:i],
#"id": [tvdbIDs objectAtIndex:i]};
[tvShowInfos addObject:info];
}
You can then sort that array easily:
[tvShowInfos sortUsingDescriptors:#[ [[NSSortDescriptor alloc] initWithKey:#"show" ascending:YES] ]];
If you need an array that contains all networks, sorted by show title, you can then use valueForKey: on the array of dictionaries:
NSArray *networksSortedByShow = [tvShowInfos valueForKey:#"network"];

Use existing NSArray object properties to create a new NSArray for sectioned tableView

So I have the kind of classic situation where I want to group my tableView by Month/Year. I have a member of my conference object called beginDateSearchString that I use to put different conference into buckets; my problem is in the next part where I try and fail to use a NSSortDescriptor to sort each bucket by beginDate (which is a date).
I am getting an error related to unsorted not being able to receive sort descriptor type selectors.
Here is the disgusting code:
- (NSArray *)arrayOfDateSortedEvents {
NSMutableArray *sortedArray = [[NSMutableArray alloc] init];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//place into buckets
for (WSConference *conference in self.arrayOfEvents) {
if (![dictionary objectForKey:[conference beginDateSearchString]]) {
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:conference,nil];
[dictionary setObject:array forKey:[conference beginDateSearchString]];
}
else {
[[dictionary objectForKey:[conference beginDateSearchString]] addObject:conference];
}
}
//sort each bucket by descriptor beginDate
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"beginDate" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:descriptor];
for (NSMutableArray *unsorted in dictionary) {
[unsorted sortUsingDescriptors:sortDescriptors];
}
// now, unkey and add dictionary in order
while ([dictionary count] > 0) {
NSString *lowest = nil;
for (NSMutableArray *array in dictionary) {
if (!lowest)
lowest = [[dictionary allKeysForObject:array] objectAtIndex:0];
else {
if ([(WSConference *)[array objectAtIndex:0] beginDate] < [[dictionary objectForKey:lowest] beginDate])
lowest = [[dictionary allKeysForObject:array] objectAtIndex:0];
}
}
[sortedArray addObject:[dictionary objectForKey:lowest]];
[dictionary removeObjectForKey:lowest];
}
return sortedArray;
}
You want to probably filter the array in addition to sorting. See NSPredicate and the NSArray method -filteredArrayUsingPredicate: Then create an eventsByDateArray of the eventArrays created by the filter. Then in your table view delegate for creating the cells, if everything is ordered properly, the first section would represent the date of the events in the eventArray that is the first object of the eventsByDateArray and the table rows would consist of the events in the eventArray. And so on for each date.
Added
Your fast enumeration is incorrect. You enumerate through the keys of the dictionary. So in your code unsorted equals each of the keys as it enumerates. This is a GREAT lesson to everyone. It does not matter how you 'type' a variable. When Objective-C compiles it turns them all into id. So NSMutableArray *unsorted is not an NSMutableArray unless it is assigned to an NSMutableArray. If you assign unsorted to an NSString it will be an NSString. The fast enumerator for a dictionary works using the keys. So, in this case, unsorted becomes an NSString.
Instead of:
for (NSMutableArray *unsorted in dictionary) {
[unsorted sortUsingDescriptors:sortDescriptors];
}
you should have this:
for (id key in dictionary) {
NSMutableArray *unsorted = [dictionary objectForKey:key];
[unsorted sortUsingDescriptors:sortDescriptors];
}

Using #min,#max and etc inside a predicate?

Is it possible to use aggregate operator such as #min inside a predicate?
BTW The predicate filters an array of objects.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY SELF.score == #min.score"];
I know you can retrieve the min value using the key-value operators eg:
NSNumber *minScore = [myArray valueForKeyPath:#"#min.score"];
So far I only get errors about the objects not being key value compliant for "#min".
Thanks
The reason that you're getting that error is that the predicate is being applied to each object in myArray, and those objects apparently don't support the key path #min.score. NSPredicate does have support for at least some of the collection operators, though. Here's a simple example that works:
NSDictionary *d1 = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:35] forKey:#"score"];
NSDictionary *d2 = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:52] forKey:#"score"];
NSDictionary *d3 = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:13] forKey:#"score"];
NSDictionary *d4 = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:19] forKey:#"score"];
NSArray *array = [NSArray arrayWithObjects:d1, d2, d3, d4, nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.score == %#.#min.score", array];
NSLog(#"Min dictionaries: %#", [array filteredArrayUsingPredicate:predicate]);
You can see that in this case, the #min.score key path is applied to the array, which makes sense. The output is an array containing the one dictionary that contains the minimum value:
Min dictionaries: (
{
score = 13;
}
)

How to copy one NSMutableArray to another?

I have an nsmutablearray(xmlParseArray) having values firstname and id, I want to copy only firstname into another nsmutablearray(copyArray).
How can I do this?
Assumption: your xmlParseArray contains number of objects all of which have a firstname property and and an id property
NSMutableArray* nameArray = [[xmlParseArray valueForKey: #"firstname"] mutableCopy];
// nameArray is an array you own.
-valueForKey: when sent to an array causes the message -valueForKey: to be sent to each of its elements and a new array to be constructed from the return values. The -mutableCopy ensures that the result is then turned into a mutable array as per your question.
I'm guessing you mean that the first array, xmlParseArray, contains a list of NSDictionary objects which each have objects attached to the keys "firstname" and "id". One way to accomplish that would be like this:
NSMutableArray *copyArray = [[NSMutableArray alloc] initWithCapacity:[xmlParseArray count]];
for(NSDictionary *dict in xmlParseArray)
if([dict objectForKey:#"firstname"])
[copyArray addObject:[dict objectForKey:#"firstname"]];
// ...do whatever with copyArray...
[copyArray release];
NSMutableArray *arr = [NSMutableArray arrayWithObject:[copyArray objectAtIndex:0]];
or
[arr addObject:[copyArray objectAtIndex:0]];
[arr addObject:[copyArray objectAtIndex:1]];
NSMutableArray *newArray = [oldArray mutableCopy];
or
NSMutableArray *newArray = [NSMutableArray arrayWithArray:oldArray];
be aware that the objects in the array aren't copied, just the array itself (references to objects are maintained).

Sorting NSMutableDictionary data

In my application I am having a dictionary which contains Keys A-Z ie 26 characters which are not in sorted ie for eg A,B,C,......
I want to Sort first The dictionary keys alphabetically and also the sort the data related to each key and then again store that in same dictionary.
NSArray *myKeys = [mGlossaryDict allKeys];
NSArray *op = [myKeys sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
until now here I have an mGlossaryDict which is an Mutabledictionary which is sorted but i need to sort the data from each of the key.
Please help me out.
NSArray *myKeys = [mGlossaryDict allKeys];
NSArray *sortedKeys = [myKeys sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSMutableArray *sortedValues = [[[NSMutableArray alloc] init] autorelease];
for(id key in sortedKeys) {
id object = [myGlossaryDict objectForKey:key];
[sortedValues addObject:object];
}