How to order NSMutableArray with NSMutableArray inside - iphone

I need so sort an array with an array inside, something like this:
NSMutableArray * array_example = [[NSMutableArray alloc] init];
[array_example addObject:[NSMutableArray arrayWithObjects:
string_1,
string_2,
string_3,
nil]
];
how can i order this array by the field "string_1" of the array???
any idea how can i do that?
Thanks

For iOS 4 and later, this is easily done using a comparator block:
[array_example sortUsingComparator:^(NSArray *o1, NSArray *o2) {
return (NSComparisonResult)[[o1 objectAtIndex:0] compare:[o2 objectAtIndex:0]];
}];
If you're interested in how blocks work, you can have a look at Apple's Short Practical Guide to Blocks.
If you wish to support iOS 3.x, you'd have to use a custom comparison function:
NSComparisonResult compareArrayFirstElement(NSArray *o1, NSArray *o2) {
return [[o1 objectAtIndex:0] compare:[o2 objectAtIndex:0]];
}
and then use:
[array_example sortUsingFunction:compareArrayFirstElement context:nil];

You can loop the array objects and call sortedArrayUsingSelector on each sub array, then replaceObjectAtIndex:withObject to inject back into the original array
NSMutableArray * array_example = [[NSMutableArray alloc] init];
[array_example addObject:[NSMutableArray arrayWithObjects:
#"z",
#"a",
#"ddd",
nil]
];
[array_example addObject:[NSMutableArray arrayWithObjects:
#"g",
#"a",
#"p",
nil]
];
NSLog(#"Original Array: %#", array_example);
for(int i = 0; i < [array_example count] ; i++){
[array_example replaceObjectAtIndex:i withObject:[[array_example objectAtIndex:i] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)]];
// order sub array
}
NSLog(#"Sorted Array: %#", array_example);

Related

i had 2 arrays with objects and the same nameobject should be cancelled only one time

I have input as two arrays shown below
NSArray *array1=[[NSArray alloc]initWithObjects:#"1",#"2",#"3", nil];
NSArray *array2=[[NSArray alloc]initWithObjects:#"1",#"2",#"1", nil];
the output should resemble like this.
the same element should be cancelled only one time.
NSArray *array3=[[NSArray alloc]initWithObjects:#"1",#"2", nil];
THANKS IN ADVANCE.....
NSArray *array1 = #[#"1",#"2",#"3"];
NSArray *array2 = #[#"1",#"2",#"1"];
NSMutableSet *allElemets = [NSSet setWithArray:array1];
[allElemets addObjectsFromArray:array2];
This will return you all elements without duplicates.
In this case it will be
#"1",#"2",#"3"
Edit:
This will return the intersection of the arrays
NSMutableSet *set1 = [NSMutableSet setWithArray:array1];
NSSet *set2 = [NSSet setWithArray:array2];
[set1 intersectSet:set2];
Use NSCountedSet for the above situation
NSMutableArray *array1=[[NSMutableArray alloc]initWithObjects:#"r",#"a",#"r",#"r",#"r", nil];
NSArray *array2=[[NSArray alloc]initWithObjects:#"b",#"c",#"r", nil];
NSMutableSet *setOne = [NSMutableSet setWithArray: array1];
NSSet *setTwo = [NSSet setWithArray: array2];
[setOne unionSet:setTwo];
NSArray *arrayOneResult = [setOne allObjects];
NSLog(#"%#",arrayOneResult);
NSMutableArray *resultArray = [[NSMutableArray alloc]init];
NSCountedSet *set = [[NSCountedSet alloc] initWithArray:arrayOneResult];
for (id item in set)
{
NSCountedSet *set1 = [[NSCountedSet alloc] initWithArray:array1];
NSCountedSet *set2 = [[NSCountedSet alloc]initWithArray:array2];
int diff = abs([set1 countForObject:item] - [set2 countForObject:item]);
for (int i = 0 ;i < diff ;i++ ) {
[resultArray addObject:item];
}
}
NSLog(#"the array : %#",resultArray );
f you are fine with sets instead of arrays, you can use NSMutableSet instead of NSArray. NSMutableSet has nice methods like intersectSet: and minusSet:
if([[array1 objectAtIndex:i] isEqualToString:[array2 objectAtIndex:i]])
{
[array2 removeObjectAtIndex: i];
NSLog(#"same element removed.");
}
array3 = [firstArray arrayByAddingObjectsFromArray:secondArray];
or
NSMutableSet *set = [NSMutableSet setWithArray:array1];
[set addObjectsFromArray:array2];
array3 = [set allObjects];
Two arrays are compared and duplicate values are removed, you get your values.
Here tHe Code goes
EDIt: This WOuld remove the Duplicate Value add Unique value.
NSArray *array1=[[NSArray alloc]initWithObjects:#"1",#"2",#"3", nil];
NSArray *array2=[[NSArray alloc]initWithObjects:#"1",#"2",#"1", nil];
//Here Create nEw Array with Arra1
NSMutableArray * newArray =[[NSMutableArray alloc] initWithArray:array1];
for(int index=0; index<[array2 count];index++)
{
id object =[array2 objectAtIndex:index];
if(![newArray containsObject:object])//this methods Returns YES/NO
{
[newArray addObject: object];
}
}

Sorting two NSMutableArrays by 'nearest distance' first

I have two arrays, both full of NSString objects like this:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
How can I sort both arrays by the nearest distance first?
So the results would be like this:
titles = #"Title5", #"Title4", #"Title2", #"Title1", #"Title3"
distances = #"8.29", #"10.29", #"23.78", #"139.45", #"347.82"
I understand that NSSortDescriptor can be used in these circumstances but after looking through the documentation, I am still unsure about how.
I would sort the distances this way...
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSArray *sortedDistances = [listItem sortedArrayUsingComparator: ^(id a, id b) {
NSNumber *aNum = [f numberFromString:a];
NSNumber *bNum = [f numberFromString:b];
return [aNum compare:bNum];
}];
I can't think of a particularly quick way to get the associated titles sorted, but this should work ...
NSMutableArray *sortedTitles = [NSMutableArray array];
NSDictionary *distanceTitle = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
for (NSString *distance in sortedDistances) {
NSString *associatedTitle = [distanceTitle valueForKey:distance];
[sortedTitles addObject:associatedTitle];
}
You can use an NSComparator block and use NSArray's sortedArrayUsingComparator method. On that block, you will receive two objects to compare, and base on the comparison result, you can use NSMutableArray exchangeObjectAtIndex:withObjectAtIndex: method to change the values of titles.
Here is a sample how I sort an array of dictionaries by distance value:
-(void)reorderByDistance {
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
self.contentArray = [self.contentArray sortedArrayUsingDescriptors:sortDescriptors];
}
And my dictionary looks like this:
NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:#"1", #"id", #"Business #1", #"name", #"This business does some pretty remarkable things", #"description", #"Alley Bar", #"category", #"1.2", #"distance", nil];
One approach would be to create a dictionary mapping titles to distances, sort the distances, and then iterate through the distances to recreate the titles:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
//Create a map of current titles to distances
NSDictionary *titleDistanceMap = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
//Need to sort the strings as numerical values
[distances sortUsingComparator:^(NSString *obj1, NSString *obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//Now re-populate the titles array
[titles removeAllObjects];
for (NSString *distance in distances){
[titles addObject:[titleDistanceMap objectForKey:distance]];
}

how to create an array of string or float in Objective-C

i need some help here, i need to know how to create an array of string retrieved from an array. i'm using powerplot for graph and it only accept float or string array.
i need to create something something like this dynamically.
NSString * sourceData[7] = {#"2", #"1", #"4", #"8", #"14", #"15", #"10"};
Below are my code to find out the numbers in strings.
NSInteger drunked = [appDelegate.drinksOnDayArray count];
NSMutableArray * dayArray = [[NSMutableArray alloc] init];
NSMutableArray * sdArray = [[NSMutableArray alloc] init];
//float *sdArray[7];
for (int i=0; i<drunked; i++) {
DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i];
NSString * dayString= [NSDate stringForDisplayFromDateForChart:drinksOnDay.dateConsumed];
[dayArray addObject:dayString];
NSLog(#"%#",[dayArray objectAtIndex:i]);
drinksOnDay.isDetailViewHydrated = NO;
[drinksOnDay hydrateDetailViewData];
NSString * sdString= [NSString stringWithFormat:#"%#", drinksOnDay.standardDrinks];
[sdArray addObject:sdString];
NSString *tempstring;
NSLog(#"%#",[sdArray objectAtIndex:i]);
}
thanks for the help :)
Array's in Objectice-C aren't that hard to work with:
NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:#"first string"]; // same with float values
[myArray addObject:#"second string"];
[myArray addObject:#"third string"];
int i;
int count;
for (i = 0, count = [myArray count]; i < count; i = i + 1)
{
NSString *element = [myArray objectAtIndex:i];
NSLog(#"The element at index %d in the array is: %#", i, element); // just replace the %# by %d
}
You can either use NSArray or NSMutableArray - depending on your needs, they offer different functionality.
Following tutorial covers exactly what you are looking after:
http://www.cocoalab.com/?q=node/19
You can also add the elements to the array when you init (and optionally add them later only if you are using the Mutable version of a collection class:
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:#"2", #"1", #"4", #"8", #"14", #"15", #"10", nil];
[myArray addObject:#"22"];
[myArray addObject:#"50"];
//do something
[myArray release];
You can use malloc to create a C-style array. something like this should work:
NSString **array = malloc(numElements * sizeof(NSString *))
some code here
free(array)
Be aware that unlike NSMutable array, c arrays won't do a retain, so you have to manage it if needed. And don't forget the free

Add an array value to another array

How can I add an array value to another array?
I get the array using:
NSMutableArray *pointsArray = [[result componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] retain];
I want to add the first and the last value of pointsArray to another array.
[array addObject:[pointsArray objectAtIndex:0]]; //First Object
[array addObject:[pointsArray lastObject]]; //Last Object
But this array should be an NSMutableArray.
Get the value of array using objectAtIndex: method of NSArray.
as follows
NSUInteger totObjects = [pointsArray count];
[yourOtherArray addObject:[pointsArray objectAtIndex:0]]; //First Object
[yourOtherArray addObject:[pointsArray objectAtIndex:totObjects-1]]; //Last Object
Its simple just add like this
NSArray *otherArray = [[NSArray alloc] initWithObjects: [pointsArray objectAtIndex:0], [pointsArray objectAtIndex:[pointsArray count]-1],nil];
This can be achieved by using this:
NSMutableArray *recentPhotos = [[NSMutableArray alloc] init];
//add one object to the array
[recentPhotos addObject: selectPhotos];

iPhone: counting unique items in an array [duplicate]

I need to perform what I feel is a basic function but I can't find any documentation on how to do it. Please help!
I need to count how many times a certain object occurs in an array. See example:
array = NSArray arrayWithObjects:#"Apple", #"Banana", #"Cantaloupe", #"Apple", #"DragonFruit", #"Eggplant", #"Apple", #"Apple", #"Guava",nil]retain];
How can I iterate through the array and count the number of times it finds the string #"Apple"?
Any help is appreciated!
One more solution, using blocks (working example):
NSInteger occurrences = [[array indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {return [obj isEqual:#"Apple"];}] count];
NSLog(#"%d",occurrences);
As #bbum said, use an NSCounted set. There is an initializer thet will convert an array directly into a counted set:
NSArray *array = [[NSArray alloc] initWithObjects:#"A", #"B", #"X", #"B", #"C", #"D", #"B", #"E", #"M", #"X", nil];
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
NSLog(#"%#", countedSet);
NSLog output:
(D [1], M [1], E [1], A [1], B [3], X [2], C [1])
Just access items:
count = [countedSet countForObject: anObj]; ...
A Simple and specific answer:
int occurrences = 0;
for(NSString *string in array){
occurrences += ([string isEqualToString:#"Apple"]?1:0); //certain object is #"Apple"
}
NSLog(#"number of occurences %d", occurrences);
PS: Martin Babacaev's answer is quite good too. Iteration is faster with blocks but in this specific case with so few elements I guess there is no apparent gain. I would use that though :)
Use an NSCountedSet; it'll be faster than a dictionary and is designed to solve exactly that problem.
NSCountedSet *cs = [NSCountedSet new];
for(id anObj in someArray)
[cs addObject: anObj];
// then, you can access counts like this:
.... count = [cs countForObject: anObj]; ...
[cs release];
Just came across this pretty old question. I'd recommend using a NSCountedSet:
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
NSLog(#"Occurrences of Apple: %u", [countedSet countForObject:#"Apple"]);
I would encourage you to put them into a Dictionary (Objective C's version of a map). The key to the dictionary is the object and the value should be the count. It should be a MutableDictionary of course. If the item is not found, add it and set the count to 1.
- (int) numberOfOccurrencesForString:(NSString*)needle inArray:(NSArray*)haystack {
int count = 0;
for(NSString *str in haystack) {
if([str isEqualToString:needle]) {
count++;
}
}
return count;
}
I up-voted Rob's answer, but I wanted to add some code that I hope will be of some assistance.
NSArray *array = [[NSArray alloc] initWithObjects:#"A", #"B", #"B", #"B", #"C", #"D", #"E", #"M", #"X", #"X", nil];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
for(int i=0; i < [array count]; i++) {
NSString *s = [array objectAtIndex:i];
if (![dictionary objectForKey:s]) {
[dictionary setObject:[NSNumber numberWithInt:1] forKey:s];
} else {
[dictionary setObject:[NSNumber numberWithInt:[dictionary objectForKey:s] intValue]+1 forKey:s];
}
}
for(NSString *k in [dictionary keyEnumerator]) {
NSNumber *number = [dictionary objectForKey:k];
NSLog(#"Value of %#:%d", k, [number intValue]);
}
If the array is sorted as in the problem statement then you don't need to use a dictionary.
You can find the number of unique elements more efficiently by just doing 1 linear sweep and incrementing a counter when you see 2 consecutive elements being the same.
The dictionary solution is O(nlog(n)), while the linear solution is O(n).
Here's some pseudo-code for the linear solution:
array = A,B,B,B,B,C,C,D,E,M,X,X #original array
array = array + -1 # array with a dummy sentinel value to avoid testing corner cases.
# Start with the first element. You want to add some error checking here if array is empty.
last = array[0]
count = 1 # you have seen 1 element 'last' so far in the array.
for e in array[1..]: # go through all the elements starting from the 2nd one onwards
if e != last: # if you see a new element then reset the count
print "There are " + count + " " + last elements
count = 1 # unique element count
else:
count += 1
last = e
the complete code with reference to #bbum and #Zaph
NSArray *myArray = [[NSArray alloc] initWithObjects:#"A", #"B", #"X", #"B", #"C", #"D", #"B", #"E", #"M", #"X", nil];
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:myArray];
for (NSString *item in countedSet) {
int count = [countedSet countForObject: item];
NSLog(#"the String ' %# ' appears %d times in the array",item,count);
}
Thank you.
If you want it more generic, or you want to count equals/different objects in array, try this:
Sign "!" count DIFFERENT values. If you want SAME values, remove "!"
int count = 0;
NSString *wordToCheck = [NSString string];
for (NSString *str in myArray) {
if( ![str isEqualToString:wordToCheck] ) {
wordToCheck = str;
count++;
}
}
hope this helps the community!
I've used it to add correct number of sections in uitableview!
You can do this way,
NSArray *array = [[NSArray alloc] initWithObjects:#"A", #"B", #"X", #"B", #"C", #"D", #"B", #"E", #"M", #"X", nil];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:array];
NSArray *uniqueStates = [[orderedSet set] allObjects];
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
for(int i=0;i<[uniqueStates count];i++){
NSLog(#"%# %d",[uniqueStates objectAtIndex:i], [countedSet countForObject: [uniqueStates objectAtIndex:i]]);
}
The result is like : A 1