PDA

View Full Version : Sort Array Question




larswik
Aug 1, 2012, 06:57 PM
I am wondering what is happening behind the scenes here. The code works fine but I was kind of expecting it to add the sorted object to the Array.

I created a Class called BoilerPlateCode which I am putting often used methods in to that I will need to call. I wrote a method that sorts an NSArray and returns NSMutableArray.


-(NSMutableArray*)sortArray: (NSArray*) incomingArray{
NSArray *tempArray = [incomingArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSMutableArray * makeMutableArray = [NSArray arrayWithArray:tempArray];

return makeMutableArray;
}


I then call it like this

BoilerPlateCode *bpc = [[BoilerPlateCode alloc] init];
staticSkills = [[NSMutableArray alloc] initWithObjects:@"Demon Lore", @"Sword",@"Preception",@"Surgery", @"Tracking",nil];
staticSkills = [bpc sortArray: staticSkills];


My question is... The last line of code "staticSkills = [bpc sortArray: staticSkills];" takes the Array, sorts it and then returns it to the same Array object. Since I never removed the objects from the array in the first place I would think that it would have an accumulative result with a duplicate set of objects in it since it is a mutableArray?



stirfie
Aug 2, 2012, 12:30 AM
staticSkills is just a pointer to a block of memory,
you have initialized it as an Array, and pointed it at the first array ( that you created manually ) then pointed it to the array that you created with your method.

So what you get in the end is a pointer to the array your method created.

On another note, if you have a class with methods that you will use from time to time, why not make them Class Methods.

+(NSMutableArray*)sortArray: (NSArray*) incomingArray{
NSArray *tempArray = [incomingArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSMutableArray * makeMutableArray = [NSArray arrayWithArray:tempArray];

return makeMutableArray;
}


this way you can use it with out having to create a new instance everytime.

NSMutableArray* staticSkills = [BoilerPlateCode sortArray:[NSArray arrayWithObjects:@"Demon Lore", @"Sword",@"Preception",@"Surgery", @"Tracking",nil]];

larswik
Aug 2, 2012, 03:17 AM
I have never used class method before in my own classes. I have always instantiated an object to use them. Perhaps this is a good chance to start using them and get comfortable with them.

Thanks for the explanation of the array. I see what is happening.

Duncan C
Aug 2, 2012, 08:10 AM
I am wondering what is happening behind the scenes here. The code works fine but I was kind of expecting it to add the sorted object to the Array.

I created a Class called BoilerPlateCode which I am putting often used methods in to that I will need to call. I wrote a method that sorts an NSArray and returns NSMutableArray.


-(NSMutableArray*)sortArray: (NSArray*) incomingArray{
NSArray *tempArray = [incomingArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSMutableArray * makeMutableArray = [NSArray arrayWithArray:tempArray];

return makeMutableArray;
}


I then call it like this

BoilerPlateCode *bpc = [[BoilerPlateCode alloc] init];
staticSkills = [[NSMutableArray alloc] initWithObjects:@"Demon Lore", @"Sword",@"Preception",@"Surgery", @"Tracking",nil];
staticSkills = [bpc sortArray: staticSkills];


My question is... The last line of code "staticSkills = [bpc sortArray: staticSkills];" takes the Array, sorts it and then returns it to the same Array object. Since I never removed the objects from the array in the first place I would think that it would have an accumulative result with a duplicate set of objects in it since it is a mutableArray?


In addition to what others have said, be aware that your code is not doing what you think it is. The last line in your sortArray method (marked in bold above) is creating a regular array, not a mutable array. You should change it like this

NSMutableArray * makeMutableArray = [tempArray mutableCopy];

larswik
Aug 2, 2012, 01:36 PM
This whole method seemed like it suffered from an extra step when I wrote it. I first wrote the line of code that sorts the array as a mutable array but I got an error about the return type being an NSArray.

Since the user will add objects to this array I had to keep it mutable so I had to take the extra step of creating a new mutable Array and assigning the non mutable array to it before returning it.

But your response brought up another question as I am still working on figuring out the behind the scenes with pointers and such. I always have to remind myself that I am working with pointers.

So this code.

NSMutableArray * makeMutableArray = [NSArray arrayWithArray:tempArray];


So with this code I am saying that I am using the "arrayWithArray" Method from the NSArray Class that is taking a pointer argument to an NSArray called tempArray. I then create a new object of type NSMutableArray which I assign the pointer makeMutableArray to that memory location.

So basically now I am assigning the tempArray pointer to the makeMutableArray pointer and the makeMutableArray pointer is simply pointing to the tempArray memory location?

Is this why you say it is not doing what I thought it was?

Thanks again for your help.

Duncan C
Aug 2, 2012, 05:02 PM
This whole method seemed like it suffered from an extra step when I wrote it. I first wrote the line of code that sorts the array as a mutable array but I got an error about the return type being an NSArray.

Since the user will add objects to this array I had to keep it mutable so I had to take the extra step of creating a new mutable Array and assigning the non mutable array to it before returning it.

But your response brought up another question as I am still working on figuring out the behind the scenes with pointers and such. I always have to remind myself that I am working with pointers.

So this code.

NSMutableArray * makeMutableArray = [NSArray arrayWithArray:tempArray];


So with this code I am saying that I am using the "arrayWithArray" Method from the NSArray Class that is taking a pointer argument to an NSArray called tempArray. I then create a new object of type NSMutableArray which I assign the pointer makeMutableArray to that memory location.

So basically now I am assigning the tempArray pointer to the makeMutableArray pointer and the makeMutableArray pointer is simply pointing to the tempArray memory location?

Is this why you say it is not doing what I thought it was?

Thanks again for your help.


The NSArray method arrayWithArray takes an array/mutable array as input, and returns a new, immutable array as a result.

You then store that immutable array into your makeMutableArray variable. Just because the variable is declared as an NSMutableArray data type, that does not make it a mutable array. It's not.

larswik
Aug 3, 2012, 12:47 AM
Gotcha, Thanks Duncan.

Duncan C
Aug 3, 2012, 01:15 PM
This whole method seemed like it suffered from an extra step when I wrote it. I first wrote the line of code that sorts the array as a mutable array but I got an error about the return type being an NSArray.

Since the user will add objects to this array I had to keep it mutable so I had to take the extra step of creating a new mutable Array and assigning the non mutable array to it before returning it.

But your response brought up another question as I am still working on figuring out the behind the scenes with pointers and such. I always have to remind myself that I am working with pointers.

So this code.

NSMutableArray * makeMutableArray = [NSArray arrayWithArray:tempArray];


So with this code I am saying that I am using the "arrayWithArray" Method from the NSArray Class that is taking a pointer argument to an NSArray called tempArray. I then create a new object of type NSMutableArray which I assign the pointer makeMutableArray to that memory location.

So basically now I am assigning the tempArray pointer to the makeMutableArray pointer and the makeMutableArray pointer is simply pointing to the tempArray memory location?

Is this why you say it is not doing what I thought it was?

Thanks again for your help.

It sounds to me like you're confused about classes and types, and how to craft methods that take the correct type and return the correct type of object.

If you are starting with a mutable array, there are methods that let you sort that array "in place" without creating a second array. Take a look at the NSMutableArray Class reference in Xcode. The mutable array equivalent of your sortedArrayUsingSelector sort method is sortUsingSelector.

The NSArray method sortedArrayUsingSelector is a message you send to an NSArray, and it creates and returns a new NSArray sorted using the specified selector.

The corresponding NSMutableArray method sortUsingSelector is sent to the mutable array, and asks the array to sort itself using the specified selector. Once the method is finished executing, the items in the mutable array will be sorted, but there will be no new array created. That might be what you want.

larswik
Aug 3, 2012, 03:20 PM
So an NSArray can not be sorted in place because it is not mutable, it is what it is. So sorting an NSArray creates a new array object.

If you try an reassign the same pointer to the array it will have the same name but pointed to a different memory address, correct?

So myNSArray = [myNSArray sortArray......]; will this create a new pointer with the same name to a different memory address for the newly created array?

And myNSMutableArray = [myNSMutbaleArray sortArray.....]; This will just rearrange the mutablearray and not create a new pointer?

Thanks again. I am trying to learn more about the internal working. It is so easy sometime to find some code online that works and you just except it and don't question why it works. I'm constantly having to remind myself that I work with pointers to objects instead of objects themselves.

But I really enjoy programming and learning.

Duncan C
Aug 3, 2012, 08:10 PM
So an NSArray can not be sorted in place because it is not mutable, it is what it is. So sorting an NSArray creates a new array object.

If you try an reassign the same pointer to the array it will have the same name but pointed to a different memory address, correct?

So myNSArray = [myNSArray sortArray......]; will this create a new pointer with the same name to a different memory address for the newly created array?

And myNSMutableArray = [myNSMutbaleArray sortArray.....]; This will just rearrange the mutablearray and not create a new pointer?

Thanks again. I am trying to learn more about the internal working. It is so easy sometime to find some code online that works and you just except it and don't question why it works. I'm constantly having to remind myself that I work with pointers to objects instead of objects themselves.

But I really enjoy programming and learning.


You've got it for the most part. However, methods that sort a mutable array don't take the form

result = [my_mutable_array sort...];

Instead, you just call

[my_mutable_array sort...];


The method doesn't return a result. Instead, the array gets sorted in place. (You send a message to the mutable array object saying "sort yourself using the following sort criteria.")

larswik
Aug 4, 2012, 12:26 AM
Got that now, thank you.

NSArrays as "set-in-stone" arrays once created. They can't sort themselves but return a new array object that has been sorted.

Do NSArrays take up less memory because they are defined and can't be changed?

Duncan C
Aug 4, 2012, 06:33 PM
Got that now, thank you.

NSArrays as "set-in-stone" arrays once created. They can't sort themselves but return a new array object that has been sorted.

Do NSArrays take up less memory because they are defined and can't be changed?

I can't give you specifics, but NSArrays are more efficient than NSMutableArrays.

I can't say for certain if it's memory efficiency, speed, or both, but I strongly suspect it's both.