Sorting Multiple NSMutableArray's - iphone

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"];

Related

How to compare two dictionary

I have two array of dictionaries and i want to compare them
Actually the dictionary structure is like the interest list of Facebook, like below
I want to find out the common interest between me and my friend
I retrieved the interest list of both user, but while I am comparing the dictionary of interests as the created_time differs so I am not getting the common dictionary
category = "Musical instrument";
"created_time" = "2011-06-11T09:10:07+0000";
id = 113099055370169;
name = Guitar;
and
category = "Musical instrument";
"created_time" = "2013-09-27T06:02:28+0000";
id = 113099055370169;
name = Guitar;
Can anybody suggest any efficient way to do this
Now I am using but it is not giving me the common interests as created_time different
for (int count = 0; count < [arrFriendsInterest count]; count++)
{
NSDictionary *dictFriend = [arrFriendsInterest objectAtIndex:count];
if ([arrMyIntrest containsObject:dictFriend]) {
[arrMutualInterest addObject:dictFriend];
}
}
where arrFriendsInterest is array of dictionaries containing friend's interest
and arrMyIntrest is the array of dictionaries containing my interests×Comments may only be edited for 5 minutes×Comments may only be edited for 5 minutes×Comments may only be edited for 5 minutes
First of all are you store that data in NSArray?
If YES then please use following code much more easily to use.
// Do any additional setup after loading the view, typically from a nib.
NSArray *ar1 = [NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:#"Musical instrument",#"category",#"2011-06-11T09:10:07+0000",#"created_time",#"113099055370169",#"id", #"Guitar",#"name", nil], nil];
NSArray *ar2 = [NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:#"Musical instrument",#"category",#"2013-09-27T06:02:28+0000",#"created_time",#"113099055370169",#"id", #"Guitar",#"name", nil], nil];
NSMutableSet* set1 = [NSMutableSet setWithArray:ar1];
NSMutableSet* set2 = [NSMutableSet setWithArray:ar2];
[set1 unionSet:set2]; //this will give you only the obejcts that are in both sets
NSArray* result = [set1 allObjects];
NSLog(#"%#",[result mutableCopy]);
Happy Coding.!!!
This assumes that you only need to compare "id" values:
NSArray* myIds = [arrMyInterest valueForKey:#"id"];
for (int count = 0; count < [arrFriendsInterest count]; count++) {
NSDictionary *dictFriend = [arrFriendsInterest objectAtIndex:count];
// Not clear whether "id" is NSString or NSNumber -- use whichever
NSString* friendId = [dictFriend valueForKey:#"id"];
if ([myIds containsObject:friendId]) {
[arrMutualInterest addObject:dictFriend];
}
}
instead of using NSDictionary why don't using custom classes?
You can have a lot of benefits:
code completion
compile-time checking
custom isEqual method
code is self-explained

Delete only one item from array having same multiple values

There is an array in my app having multiple same values in it. I need to delete only one value at a time from array whether it has same more values in it.
Level1 Business,
Level2 Economy,
Level2 Economy,
Level1 Business
How this can be achieved, and main thing is that these values are dynamic these can be more or less also. Please guide for above.
Below is what i tried.
if([arr containsObject:[NSString stringWithFormat:#"%d",ind]]){
[arr removeObject:[NSString stringWithFormat:#"%d",ind]];
}
This thing removes all similar entries, not required. Thanks in advance.
try like this,
NSArray *array = [NSArray arrayWithObjects:#"Level1 Business", #"Level2 Economy", #"Level2 Economy", #"Level1 Business", nil];
NSMutableArray *mainarray=[[NSMutableArray alloc]initWithArray:array];
int n=[mainarray indexOfObject:#"Level2 Economy"];//it gives first occurence of the object in that array
if(n<[mainarray count]) // if the object not exist then it gives garbage value that's why here we have to take some condition
[mainarray removeObjectAtIndex:n];
NSLog(#"%#",mainarray);
O/P:-
(
"Level1 Business",
"Level2 Economy",
"Level1 Business"
)
As you say,
[array removeObject:#"SomeObject"];
removes all instances of where isEqual: returns YES. To remove only the first instance, you can use something like
NSUInteger index = [array indexOfObject:#"SomeObject"];
if(index != NSNotFound) {
[array removeObjectAtIndex:index];
}
Use [arr removeObjectAtIndex:yourIndex ] to remove your object at perticular postion at dynamic
Sample Code :
NSMutableArray *arr = [[NSMutableArray alloc]initWithObjects:#"hello",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",#"hi",nil];
NSUInteger obj = [arr indexOfObject:#"hi"]; //Returns the lowest integer of the specified object
[arr removeObjectAtIndex:obj]; //removes the object from the array
NSLog(#"%#",arr);
In your Case :
if([arr containsObject:[NSString stringWithFormat:#"%d",ind]])
{
NSUInteger obj = [arr indexOfObject:[NSString stringWithFormat:#"%d",ind]]; //Returns the lowest integer of the specified object
[arr removeObjectAtIndex:obj];
}
Here your requirement is like definition of NSSet, which contains unique objects only.
But this will implies only if both the same value objects, are really in referring to same memory location as well.
If this is the case then and then, you can try code mentioned below:
// create set from an array
NSSet *telephoneSet = [NSSet setWithArray: myArray];
// create array from a set
NSMutableArray *array = [NSMutableArray arrayWithArray:[set allObjects]];
I don't know whether it will work for your requirement or not. But for that, it would be required to check the object equality level.
Still it might help you as an less line of code.
NSMutableArray *uniques= [[NSMutableArray alloc] init];
for (NSString *word in duplicateWordsArray){
if (!uniques.contains(word)){
[ uniques addObject:word];
}
}
I wrote this from my phone so it isn't formatted for code, but this will do it for you quickly and you'll have an array (uniquearray) that has unique words. Then you can use that one or set your original array = to unique array
NSArray *input = [NSArray arrayWithObjects:#"Level1 Business", #"Level2 Economy", #"Level2 Economy", #"Level1 Business", nil];
NSMutableArray *output = [[NSMutableArray alloc] init];
[output addObject:[input objectAtIndex:0]];
for(NSString *value in input) {
if(![output containsObject:value])
[output addObject:value];
}

Empty NSMutableArray , not sure why

Ok so I populate the array like this:
NSMutableArray *participants;
for(int i = 0; i < sizeofpm; i++){
NSDictionary *pmpart_dict = [pm_participants objectAtIndex:i];
NSString *pmpart_email = [pmpart_dict objectForKey:#"email"];
NSString *pmpart_email_extra = [#"pm" stringByAppendingString:pmpart_email];
[participants setValue:pmpart_email forKey:pmpart_email_extra];
NSLog(#"%#", participants);
}
sizeofpm is 1. that is using count. to get the number of values in the array. How can i store values to that array? It doesnt seem to be working. Thanks!
you need to alloc it first. Try to change the first line to:
NSMutableArray* participants = [[NSMutableArray alloc] init];
also using setValue:forKey: wont work with an NSMutableArray as an array has no key.
Try using [participants addObject:pmpart_email];.
You don't create the array, you just declare it.
NSMutableArray *participants = [NSMutableArray array];
After that, setValue:forKey: will not add objects to an array. You need addObject::
[participants addObject:pmpart_email];
There is no key.
You are assigning a value to an NSMutableArray *participants like how you assign values to an NSDictionary object. To assign values to NSMutableArray you can call - (void)addObject:(id)anObject
So, I as some of the other answer have stated, you're missing your initializer for participants. However, judging by your use of setValue:forKey:, and how you appear to be structuring your data, you're not looking for NSMutableArray, but instead NSMutableDictionary. Arrays are simply lists, whereas dictionaries maintain key-value relationships, which you appear to be attempting to leverage.
Try this:
// some classes provide shorthand for `alloc/init`, such as `dictionary`
NSMutableDictionary *participants = [NSMutableDictionary dictionary];
for(int i = 0; i < sizeofpm; i++){
NSDictionary *pmpart_dict = [pm_participants objectAtIndex:i];
NSString *pmpart_email = [pmpart_dict objectForKey:#"email"];
NSString *pmpart_email_extra = [#"pm" stringByAppendingString:pmpart_email];
[participants setValue:pmpart_email forKey:pmpart_email_extra];
NSLog(#"%#", participants);
}
This will give you a dictionary in the form of
{
pmpart_email_extra: pmpart_email
}

Sort an array with numeric strings

Hello I have an array of persons, and i am trying to sort them by age using a sort descriptor.
The age field in a patient is a string so when calling:
ageSorter = [[NSSortDescriptor alloc] initWithKey:#"age" ascending:YES];
[personList sortUsingDescriptors:[NSArray arrayWithObject:ageSorter]];
It sorts them but 100 appears first because its is not using numericSearch in the compare options.
Is there a ways i can still sort with descriptor but maybe using a selector to change how to compare the strings?
The finderSortWithLocale method (both these are taken from apple api):
int finderSortWithLocale(Person *person1, Person *person2, void *locale)
{
static NSStringCompareOptions comparisonOptions = NSNumericSearch;
NSRange string1Range = NSMakeRange(0, [string1 length]);
NSString *age1 = person1.age;
NSString *age2 = person2.age;
return [age1 compare:age2
options:comparisonOptions
range:string1Range
locale:(NSLocale *)locale];
}
How to call this method (edited: call the function on array of Persons):
NSArray *sortedArray = [personList sortedArrayUsingFunction:finderSortWithLocale
context:[NSLocale currentLocale]];
I also faced the same issue and found answer here.
Instead of NSString comparison, do with your object property. i.e for age.
Example. : In ascending order :
NSArray *sortedArray = [_arrayCaptureLeadList sortedArrayUsingComparator:^(Person *obj1, Person *obj2) {
return [obj1.age compare:obj2.age options:NSNumericSearch];
}];
NSMutableArray *filterResultArray = [NSMutableArray arrayWithArray:sortedArray];
In descending order :
NSArray *sortedArray = [_arrayCaptureLeadList sortedArrayUsingComparator:^(Person *obj1, Person *obj2) {
return [obj2.age compare:obj1.age options:NSNumericSearch];
}];
NSMutableArray *filterResultArray = [NSMutableArray arrayWithArray:sortedArray];
I know this is very late to reply your question but may this will be helpful for others. ^_^
You could create a category on NSString that adds a method numericCompare: and which calls [self compare:otherString options:NSNumericSearch]. Another option is to convert the age field into a NSNumber instead of a NSString. Yet another option involves a NSComparator block and sortUsingComparator.

Sorting NSSets of a core data entity - Objective-C

I would like to sort the data of a core data NSSet (I know we can do it only with arrays but let me explain...). I have an entity user who has a relationship to-many with the entity recipe. A recipe has the attributes name and id.
I would like to get the data such that:
NSArray *id = [[user.recipes valueForKey:#"identity"] allObjects];
NSArray *name = [[user.recipes valueForKey:#"name"] allObjects];
if I take the object at index 1 in both arrays, they correspond to the same recipe...
Thanks
You need to sort the recipes first:
NSArray *sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES]];
NSArray *sortedRecipes = [[recipes allObjects] sortedArrayUsingDescriptors:sortDescriptors];
you can then extract an array of attributes from the sorted recipes array and the results will remain in sorted order:
NSArray *sortedNames = [sortedRecipes valueForKey:#"name"];
NSArray *sortedIdentities = [sortedRecipes valueForKey:#"identity"];
If you want them to be in the same order, then you need to sort them before extracting the values. Example:
NSArray * sortedRecipes = [user.recipes sortedArrayUsingDescriptors:arrayOfSortDescriptors];
NSArray * identities = [sortedRecipes valueForKey:#"identity"];
NSArray * names = [sortedRecipes valueForKey:#"name"];
EDIT
My apologies. I just realized this is an iPhone question, and NSSet doesn't have sortedArrayUsingDescriptors: on the iPhone. However, it's trivial to work around:
NSArray * recipes = [user.recipes allObjects];
NSArray * sortedRecipes = [recipes sortedArrayUsingDescriptors:arrayOfSortDescriptors];
....