Join objects in sub-array into one array - Objective-c - ios

Is there a one-liner to do the following
NSMutableArray *allpoints = [[NSMutableArray alloc] init];
for (NSMutableArray *arr in self.points)
[allpoints addObjectsFromArray:arr];
I have an array of arrays (self.points) and I am joining all of the objects in the subarrays into a single array.

NSArray *array1 = #[ #"a", #"b", #"c" ];
NSArray *array2 = #[ #"d", #"e", #"f" ];
NSArray *array3 = #[ array1, array2 ];
NSArray * flattenedArray = [array3 valueForKeyPath:#"#unionOfArrays.self"];
NSLog(#"flattenedArray: %#", flattenedArray);
Output:
flattenedArray: (
a,
b,
c,
d,
e,
f
)

There is not a way to add all objects in an array of arrays (e.g., every NSMutableArray in self.points to another array without iterating through.
However, you could add a category to NSArray to do exactly what you're doing now, and then call it with one line later.

If you are initializing the array and adding objects at the same time then there is an initializer for that.
NSMutableArray *allpoints = [[NSMutableArray alloc] initWithArray:self.points];
If you already have the mutable array defined and you want to just append objects to the end then you can use the following.
[allpoints addObjectsFromArray:self.points];

I don't think there is a way to do this.
NSMutableArray *allpoints = [[NSMutableArray alloc] initWithArray:self.points]
would give you an array of the arrays, but there is no single line solution. I'd suggest writing a category that will do this for you so you can easily reuse it.

Related

Remove duplicates from large NSMutableArray

I have a large mutable array with lots of duplicate values in alphabetical order.
I need to be able to convert my array *Array into a new array that contains one entry for each string variant.
I am currently using:
NSArray *array = [NSArray arrayWithObjects:papersObject.paperSubject, nil];
NSCountedSet *paperSet = [[NSCountedSet alloc] initWithArray:array];
NSMutableArray *namesArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
[namesSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
if ([paperSet countForObject:obj] == 1) {
[namesArray addObject:obj];
}
}];
NSLog(#"%#", namesArray);
But this returns a long list of the same array, still with duplicates.
Any ideas?
What about:
NSArray *arrayWithNoDuplicates = [[NSSet setWithArray:papersObject.paperSubject] allObjects];
A. What is namesSet? paperSet?
B. However:
NSOrderedSet *set = [NSOrderedSet orderedSetWithArray:array];
NSArray *arrayWithUniquesIsAnOrderedSet = set.array;
BTW: I would highly recommend to use an ordered set instead of an array, because an array with unique objects is an ordered set.

Can't properly retrieve objects from NSMutableArray

I will be putting a variety of things in this mutable array, but first I am just trying to make sure it works by putting in strings, and then pulling out the strings. Here is my code
str1=#"1";
str2=#"2";
str3=#"3";
NSMutableArray *testArray;
[testArray addObject:str1];
[testArray addObject:str2];
[testArray addObject:str3];
retrieve =[testArray objectAtIndex:1];
NSLog(#"the test number is %#",retrieve);
The problem is that my string:retrieve equals "null" after receiving the string from the array. I'm not sure what I am doing wrong, I've looked at Apple's documentation but I'm having trouble making sense of it. I know I must be interacting with the array incorrectly, but I'm not sure how exactly. Help will be appreciated.
-Thank you!
You did not initialize your testArray:
NSMutableArray *testArray = [NSMutableArray array];
You can populate the array using new syntax. If you needed mutability only to add the three items, you could use a non-mutable array instead, like this:
NSArray *testArray = #[ #"1", #"2", #"3"];
If you do need mutability, call mutableCopy:
NSMutableArray *testArray = [#[ #"1", #"2", #"3"] mutableCopy];
Well, that's because testArray is nil. you should change the 4th line to
NSMutableArray *testArray = [NSMutableArray array];
You array is nil.
You are missing
NSMutableArray *testArray = [NSMutableArray array];
To clarify what others are telling you:
This line
NSMutableArray *testArray;
Does not create an array. It creates a pointer variable that can be used to point to a mutable array. It starts out containing a zero value (nil, points to nothing.)
It's like a postal address that points to an empty lot.
You need to create (allocate) and initialize a mutable array object in order to use it. (Continuing our analogy, you have to build a house and put a mailbox in front of it before the address becomes valid.)
So you need to say:
testArray = [#[ #"1", #"2", #"3"] mutableCopy];
Breaking that down:
The inner part,
#[ #"1", #"2", #"3"]
Creates an immutable array that contains 3 string objects.
Then we ask the immutable array to create a mutable copy of itself. We save the address of that newly created mutable array into the pointer variable testArray.
We could do it in 3 steps:
NSMutableArray *testArray;
NSArray *tempArray = #[ #"1", #"2", #"3"];
testArray = [tempArray mutableCopy];
Or all at once, like #dasblinkenlight's code:
NSMutableArray *testArray = [#[ #"1", #"2", #"3"] mutableCopy];

NSArray sortedArrayUsingDescriptors: New Copy or Retain?

According to NSArray class reference there are 4 type of methods to sort array:
1- sortedArrayUsingComparator:
2- sortedArrayUsingSelector:
3- sortedArrayUsingFunction:context:
4- sortedArrayUsingDescriptors:
For first three methods it mentioned :
The new array contains references to the receiving array’s elements, not copies of them.
But for the forth method (descriptor) it mentioned:
A copy of the receiving array sorted as specified by sortDescriptors.
But following example shows like the other 3 methods, descriptor also retain original array and do not return a new copy of it:
NSString *last = #"lastName";
NSString *first = #"firstName";
NSMutableArray *array = [NSMutableArray array];
NSDictionary *dict;
NSMutableString *FN1= [NSMutableString stringWithFormat:#"Joe"];
NSMutableString *LN1= [NSMutableString stringWithFormat:#"Smith"];
NSMutableString *FN2= [NSMutableString stringWithFormat:#"Robert"];
NSMutableString *LN2= [NSMutableString stringWithFormat:#"Jones"];
dict = [NSDictionary dictionaryWithObjectsAndKeys: FN1, first, LN1, last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys: FN2, first, LN2, last, nil];
[array addObject:dict];
// array[0].first = "Joe" , array[0].last = "Smith"
// array[1].first = "Robert" , array[1].last = "Jones"
NSSortDescriptor *lastDescriptor =[[NSSortDescriptor alloc] initWithKey:last
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *firstDescriptor =[[NSSortDescriptor alloc] initWithKey:first
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:descriptors];
// array[1] == sortedArray[0] == ("Robert" , "Jones")
// comparing array entries whether they are same or not:
NSLog(#" %p , %p " , [array objectAtIndex:1] , [sortedArray objectAtIndex:0] );
// 0x10010c520 , 0x10010c520
it shows objects in both arrays are same,
"A copy of the receiving array sorted as specified by sortDescriptors" means that the array object is copied not the elements in the array. The reason the documentation uses the word "copy" is to make it clear that the returned array is not the same array instance as the receiver.
Elements in an array are never copied in Cocoa with the exception of initWithArray:copyItems:YES which will copy the first level items in the original array to the new array. Even then, this copy is done by calling copyWithZone: on the elements, so caveats apply depending on what elements are in your array.
Note that Cocoa is reference counted, so the concept of "deep copies" is not inherently built in for a reason. This is also (in part) the reason why array objects in cocoa come in two flavors (NSArray and NSMutableArray) and are usually immutable (NSArray) instead of as in other languages where there is not usually a concept of immutable and mutable arrays.
see this SO answer for how to get a "deep copy" of an NSArray.

Get duplicates in NSArray

I have an NSArray which contains a few duplicate objects. I want to print which objects are getting duplicated, for example:
NSArray * array = [NSArray arrayWithObjects: A, B, C, A, B];
Now I want to print in my console A & B as these are duplicated.
How do I do this?
You can use NSCountedSet for this. you can add all the objects in a counted set, then use the countForObject: method to find out how often each object appears. read about NSCountedSet for further reference
Use an NSCountedSet and only print the elements that returns a number>1 for countForObject: method
It's probably far from perfect, but it works
NSArray *array = [NSArray arrayWithObjects:#"a", #"b", #"b", #"v", #"f", #"f", nil];
NSMutableArray *un_array = [NSMutableArray array];
NSMutableArray *dupArray = [NSMutableArray array];
for (id obj in array)
{
if (![un_array containsObject:obj])
[un_array addObject:obj];
else
[dupArray addObject:obj];
}
NSLog(#"DUPLICATES:");
for (id obj in dupArray)
NSLog(#"%#", [obj description]);
Another approach is to sort the array and look for adjacent duplicates. Probably a little slower than using a hashed set approach, but the same basic "big O".

How to initialize an empty mutable array in Objective C

I have a list of objects (trucks) with various attributes that populate a tableview. When you tap them they go to an individual truck page. There is an add button which will add them to the favorite list in another tableview. How do I initialize an empty mutable array in Cocoa?
I have the following code:
-(IBAction)addTruckToFavorites:(id)sender:(FavoritesViewController *)controller
{
[controller.listOfTrucks addObject: ((Truck_Tracker_AppAppDelegate *)[UIApplication sharedApplication].delegate).selectedTruck];
}
Update:
With new syntax you can use:
NSMutableArray *myArray = [NSMutableArray new];
Original answer:
for example:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
And here you find out why (difference between class and instance method)
Basically, there are three options:
First
NSMutableArray *myMutableArray = [[NSMutableArray alloc] init];
Second
NSMutableArray *myMutableArray = [NSMutableArray new];
Third
NSMutableArray *myMutableArray = [NSMutableArray array];
You can also initialize in this way
Another way for Objective C apart from the answer of #NSSam
NSMutableArray *myMutableArray = [#[] mutableCopy];
For Swift
let myArray = NSMutableArray()
OR
let myArray = [].mutableCopy() as! NSMutableArray;
NSMutableArray *arr = [NSMutableArray array];
I use this way to initialize an empty mutable array in Objective C:
NSMutableArray * array = [NSMutableArray arrayWithCapacity:0];
listOfTrucks = [NSMutableArray array]; gives you a new mutable array.
In modern Objective - C it could be even more shorter:
NSArray *array = #[];

Resources