How can I move the values in NSMutableArray to NSArray - ios

I have an array of recommendedcar IDs, and another array of allcar IDs. From this, I have to take the recommendedcar images. First, I check whether the recommended carid is in my allcar id; if it is, I select the corresponding car images, and store them into NSArray.
This is the code I am using.
for (int i=0;i<[listOfCarId count];i++) {
for (int j=0;j<[_allCarID count];j++) {
tempAllCarId=[_allCarID objectAtIndex:j];
tempRecommendedCarId=[listOfCarId objectAtIndex:i];
if ([tempRecommendedCarId isEqualToString:tempAllCarId]) {
_recommendedCarImage=[_allCarImages objectAtIndex:j];
NSLog(#"finalImage%#",_recommendedCarImage);
}
}
}
_recommendedcarImage is NSMUtableArray; I want a NSArray. How can I convert it to a NSArray?
How can i replace the "_recommendedCarImage " with an NSArray?? Currently _recommendedCarImage is a mutable array.

Polymorphism. Since NSMutableArray is a subclass of NSArray, you can use it anywhere an NSArray is expected. You don't have to do anything.

Now its working,What i did is , I just copy the contents of Mutable array to NSarray
recommendedArray=[_recommendedCarImage copy];

An NSMutableArray is an NSArray already (as it's a subclass of NSArray), still you can do:
NSArray *array = [NSArray arrayWithArray:mutableArray];

Related

Dictionary allKeys vs keyEnumerator?

Which to use when?
What if I am looping the dictionary and removing key-values from it, will the enumerator work for that? Documentation seem to answered that question:
If you use this method with instances of mutable subclasses of
NSDictionary, your code should not modify the entries during
enumeration. If you intend to modify the entries, use the allKeys
property to create a “snapshot” of the dictionary’s keys. Then use
this snapshot to traverse the entries, modifying them along the way.
Performance?, because people always want to know.
Iteration through NSDictionary could be achieved at least in two ways: using NSArray with [NSDictionary allKeys] or NSEnumerator.
NSArray *keyArray =  [bigUglyDictionary allKeys];
int count = [keyArray count];
for (int i=0; i < count; i++) {
  NSDictionary *tmp = [bigUglyDictionary objectForKey:[ keyArray objectAtIndex:i]];
}
NSEnumerator *enumerator = [bigUglyDictionary keyEnumerator];
id key;
while ((key = [enumerator nextObject])) {
NSDictionary *tmp = [bigUglyDictionary objectForKey:key];
}
Second way is a little bit faster, so if you work with huge dictionaries and have no need of array with their keys

Objective-C: Remove duplicates efficiently from large data structures

I have an object containing an array of NSNumbers (indexes) and an array of NSDictionaries (indexesTitles) corresponding to indexes, containing some info.
I have to call a method for each object.index and associate object.indexTitles to the returning results, saving them into a single array.
At the end of it, I want to remove indexes duplicates, preserving the associated indextTitles in an efficient way, because I'm working with large arrays.
NSMutableArray *resultArray = [NSMutableArray array];
NSMutableArray *titlesArray = [NSMutableArray array];
for(NSNumber *index in object.indexes)
{
NSArray *resultsIndexArray = [self methodThatReturnsAnArray];
NSString *indexTitleDictionary = [object.indexesTitles objectAtIndex:i];
for(NSNumber *resultId in resultsIndexArray)
{
[titlesArray addObject:indexDictionary];
[resultArray addObject:resultId];
}
i++;
}
[fullResultsArray addObject:titlesArray];
[fullResultsArray addObject:resultArray];
I've found that the most efficient way to remove duplicates is using an
NSOrderedSet like this:
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:resultArray];
resultArray = [orderedSet.array mutableCopy];
How can I remove the corresponding entries in titlesArray? how can I preserve the association?
I've also tried to use a NSDictionary like {resultId, titleDictionary} and storing them into an array, but I haven't found a efficient way to remove dictionaries with the same result, they are all too slow.
Any suggestion?
It is not completely clear to me what your problem is, maybe this will help:
A good way to remove duplicates is not to add them in the first place, replace:
for(NSNumber *resultId in resultsIndexArray)
{
[titlesArray addObject:indexDictionary];
[resultArray addObject:resultId];
}
with:
for(NSNumber *resultId in resultsIndexArray)
{
// only add if resultId not already in resultArray
if( ![resultArray containsObject:resultId] )
{
[titlesArray addObject:indexDictionary];
[resultArray addObject:resultId];
}
}
The containsObject: call requires a linear search, if your data set is large you might wish to change resultArray to an NSMutableSet and titlesArray to an NSMutableDictionary mapping from resultId to indexDictionary values.
HTH

Looping thru NSArray of NSString logic

I need help with the following:
I have an NSArray with NSStrings, I want to loop thru these strings and find a matching string, when match is found the strings after this match will be extracted into an NSDictionary until a certain other match is hit.
Here is an example:
NSArray *array = #[#"Fruit",#"Apple",#"Vegtable",#"Tomato",#"Fruit",#"Banana",#"Vegtable",#"Cucumber"];
So I want to loop thru this array and split it in 2 arrays one for fruit and one for vegetable.
Anyone can help with the logic?
Thanks
This is probably the simplest way to solve the problem:
NSArray *array = #[#"Chair",#"Fruit",#"Apple",#"Orange",#"Vegetable",#"Tomato",#"Fruit",#"Banana",#"Vegetable",#"Cucumber"];
NSMutableArray *fruitArray = [NSMutableArray array];
NSMutableArray *vegetableArray = [NSMutableArray array];
NSMutableArray *currentTarget = nil;
for (NSString *item in array)
{
if ([item isEqualToString: #"Fruit"])
{
currentTarget = fruitArray;
}
else if ([item isEqualToString: #"Vegetable"])
{
currentTarget = vegetableArray;
}
else
{
[currentTarget addObject: item];
}
}
In one iteration over the array, you just keep adding items to a result array using a pointer to one of two result arrays according to the last occurrence of the #"Fruit" or #"Vegetable" string.
This algorithm ignores all items before the first occurrence of the #"Fruit" or #"Vegetable" string, because the currentTarget is initialized to nil, which ignores the addObject: messages. If you want different behaviour, just change the initialization.
You said you wanted the results in a NSDictionary, but didn't specify what should be the key. If you want one NSDictionary with two keys, Fruit and Vegetable, and values NSArrays containing the items, just use the arrays previously created:
NSDictionary *dict = #{ #"Fruit": fruitArray, #"Vegetable": vegetableArray };
PS: You have a typo in your example, Vegtable instead of Vegetable. I corrected it in my code, so keep it in mind.
If I completely understand you:
NSArray *array = #[#"Fruit",#"Apple",#"Vegtable",#"Tomato",#"Fruit",#"Banana",#"Vegtable",#"Cucumber"];
NSMutableArray *fruits = [NSMutableArray array];
NSMutableArray *vegtables = [NSMutableArray array];
for (NSInteger i = 0; i < array.count; ++i){
if ([array[i] isEqualToString:#"Fruit"]){
++i;
[fruits addObject:array[i]];
}
else if ([array[i] isEqualToString:#"Vegtable"]){
++i;
[vegtables addObject:array[i]];
}
}

Capitalized NSArray of Strings?

I have an NSarray called array. And it look like this
array = #[#"one", #"two", #"three"];
I want this array to be capitalized. What is the best way to go about this. I can only think of making an NSMutableArray called mutableArray.
And do something like this
for(int i = 0; i < array.lenght; i++) {
self.mutableArray = addObject:[array[i] capitalizedString];
}
Or is there another better way?
The magic method you are looking for does in fact exist.
NSArray *array = #[#"one", #"two", #"three"];
NSArray *capArray = [array valueForKeyPath:#"capitalizedString"];
SWIFT
You Can use map
let array = ["one", "two", "three"]
let upercaseArray = array.map({$0.uppercased()})
now you have upercaseArray like ["ONE","TWO","THREE""]
What you really want is a sort of transform method, which takes an array and a selector, then returns an array of the results of performing that selector on each object. Unfortunately that doesn't exist in vanilla objective-C.
Your approach is generally fine, but I would be careful of two points. Firstly, make sure you create the NSMutableArray with the capacity of the NSArray you are copying, as this will avoid any reallocation overhead as you add objects to it. Secondly, you might want to copy the mutable array so you end up with an immutable NSArray as the final result.
So I would use something like this:
- (NSArray *)capitalizeStringArray:(NSArray *)array {
// Initialize tempArray with size of array
NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:array.count];
for (NSString *str in array) {
[tempArray addObject:[str capitalizedString]];
}
return [tempArray copy]; // convert back to NSArray]
}
You can convert this to a category method on NSArray if you like, and generalize it to use other selectors if you wish.
There's about a gazillion ways to handle this. For small arrays, pick whichever you find easier to understand.
I'd probably use code like this:
- (NSMutableArray *) capitalizedArrayFromArrayOfStrings: (NSArray*) array;
{
NSMutableArray *result = [NSMutableArray arrayWithCapacity: array.count];
for (NSString *string in array)
{
if ([string isKindOfClass: [NSString class]]
[result addObject: [string capitalizedString];
}
}
Creating your array with the correct capacity at the beginning enables the array to allocate enough space for all it's future elements and saves it having to allocate more space later.
Using for..in fast enumeration syntax is more efficient than using array indexing, but for short arrays the difference is small. The code is also simpler to write and simpler to read, so I prefer that syntax where possible.
As Alex says, you could also create a category method on NSArray that would return a capitalized version of your array, or even a category on NSMutableArray that would replace the strings in the array "in place".
Works like charm.
NSString *myString = YOUR_ARRAY.uppercaseString;
[myNSMutableArray addObject:myString];

NSMutableArray with NSDictionary to NSMutableDictionary

Here is the situation:
I have a request on AFNetworking that retrieves me a JSON with an NSArray.
My goal is to mutate the NSDictionaries inside it. I already made a mutableCopy of the array, but I want to know if I can easily mutate all the content. Will I have to iterate through the array manually?
NSJSONSerialization has options to allow you to control the mutability of the resulting data structure. Just pass the appropriate ones (probably NSJSONReadingMutableContainers) and there you go.
You cannot mutate NSDictionary, just because only NSMutableDictionary has method setObject:forKey:
So you should create mutableCopy of each dictionary and empty mutable array. Then with a forloop fill that array. Your code should be so:
- (NSMutableArray *)mutatedArrayFromArray:(NSArray *)array
{
NSMutableArray *resultArray = [NSMutableArray new];
if([array count] > 0)
{
for(int i = 0; i < count; i++)
{
NSMutableDictionary *mutatedItem = [[array objectAtIndex:i] mutableCopy];
[resultArray addObject:mutatedItem];
[mutatedItem release]; // only with ARC disabled
}
}
return [result autorelease]; // if ARC enabled : return result;
}

Resources