NSMutableArray keep objects at indexSet - objective-c

I am on Xcode 8.2, OSX not iOS, Objective-C
I have an NSMutableArray and an NSIndexSet. I want to remove ALL items of the array EXCEPT those at the NSIndexSet. So basically something like
[array keepObjectsAtIndexes:indexSet]; // just to carify i know this doesnt exist
What's the best way to do this? Can i somehow 'reverse' the index set?

You can construct an inverse of a given NSIndexSet by constructing an index set that has all indexes in range 0..arrayCount-1, inclusive, and then removing the indexes in your indexSet from it:
NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet initWithIndexesInRange:NSMakeRange(0, array.count)];
[indexesToRemove removeIndexes:indexesToKeep];
[array removeObjectsAtIndexes:indexesToRemove];

You can do this even without creating unnecessary arrays:
// Initial array
NSMutableArray* array = [[NSMutableArray alloc] initWithArray:#[#"one", #"two", #"three", #"four", #"five"]];
// Indices we want to keep
NSIndexSet* indexSet = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(1, 3)];
// Preparing reversed index set
NSMutableIndexSet *indexSetToRemove = [[NSMutableIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, [array count])];
[indexSetToRemove removeIndexes:indexSet];
// Removing objects from that set
[array removeObjectsAtIndexes:indexSetToRemove];
The output will be:
2017-05-11 20:10:22.317 Untitled 15[46504:32887351] (
two,
three,
four
)
Cheers

You could get the objects with objectsAtIndexes and replace the entire objects with the result.
NSArray *temp = [array objectsAtIndexes:indexSet];
[array replaceObjectsInRange:NSMakeRange(0, array.count) withObjectsFromArray: temp];

Related

Inserting NSDictionary into sorted NSMutableArray

I want to insert an NSDictionary object into an array and have the array sorted by objectForKey.
I managed to do this by inserting, re-sorting and reloading the array, which works fine, but I figured there would be a better method, which there is, I just don't know how to use it.
Current code:
-(NSMutableArray*)sortArray:(NSMutableArray*)theArray {
return [[theArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:#"n"
ascending:YES]]] mutableCopy];
}
returns the re-sorted array. Fine. Works perfectly, but... is it the most efficient?
From another question I gather that this is the method to use to find the index to insert into:
NSUInteger newIndex = [array indexOfObject:newObject
inSortedRange:(NSRange){0, [array count]}
options:NSBinarySearchingInsertionIndex
usingComparator:comparator];
[array insertObject:newObject atIndex:newIndex];
The problem is I have no idea how to use the comparator method, and if that's even possible when I want to sort by objectForKey for each index.
Can anyone exemplify the above method when the key of the object (newObject in above example) to sort by is, let's say:
[newObject objectForKey:#"sortByThis"];
Use NSSortDescriptor
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"sortByThisKey" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray = [myArray sortedArrayUsingDescriptors:sortDescriptors];
here is the simple example for comparator
- (NSComparisonResult)compareResulst:(CustomObject *)otherObject {
if(self.name isEqualToString:key)
{
return NSOrderedAscending;
}
else
{
return NSOrderedDescending
}
}
NSArray *sArray;
sArray = [unsArray sortedArrayUsingSelector:#selector(compareResulst:)];
this will sort the array. it will iterate through object and based on your if else it will move object up and down ...
Here's an example of sorting
//For make a we're adding 5 random integers into array inform of NSDictionary
//here, we're taking "someKey" to store the integer (converted to string object) into dictionary
NSMutableArray *array = [NSMutableArray array];
for(int i = 1; i<=5; i++) {
[array addObject:[NSDictionary dictionaryWithObject:[#(arc4random()%10) stringValue] forKey:#"someKey"]];
}
//create a sort descriptor to sort the array
//give the key in dictionary for which you want to perform sort
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"someKey" ascending:YES];
//we're doing self sort for mutable array, & that's it, you'll have a sorted array.
[array sortUsingDescriptors:#[sort]];
N.B.
1.Instead of "someKey" from above example you can set any key for which you want to perform sort.
2.There's some other methods for sorting, you can use the one base on your requirement.
3.see #[sort] in code. Its full version is, [NSArray arrayWithObject:sort];

NSArray: Removing every element but the first 20

I have a NSArray with possibly hundreds of elements. I want to remove every element but the 20 first ones. Ideas?
If your array is an NSArray, then you can't remove objects since it's immutable. You'll need to do something like Neo's answer. If your array is an NSMutableArray, you can use the following line to get the first 20 items:
[myArray removeObjectsInRange:NSMakeRange(20, myArray.count - 20)];
You can extract the first 20 items, and re-assign your source array:
NSArray *myHugeArray = [[NSArray alloc] initWithItems:...] // An array with, say, 1000 items
NSArray *tmpArray = [myHugeArray objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 20)]];
[myHugeArray release];
myHugeArray = [tmpArray retain];
Suppose your NSArray is yourArray, do this
NSMutableArray *temp=[[NSMutableArray alloc]initWithArray:yourArray];
for(int i=0; i<20;i++){
[temp addObject:[yourArray objectAtIndex:i]];
}
yourArray=[NSArray arrayWithArray:temp];

obj-c fetching strings from array

i'm new to obj-c (this is my first day class eheh) and i'm trying to change a label with a random string from a multidimensional array. plus, every time the button is hitten you switch the array. i know it's a bit odd eheh… this is the IBAction:
UIButton *button = (UIButton *)sender;
NSMutableArray *firstArray = [NSMutableArray array];
[firstArray addObject:#"foo"];
NSMutableArray *secondArray = [NSMutableArray array];
[secondArray addObject:#"bar"];
NSMutableArray *frasi = [NSMutableArray array];
[frasi addObject:firstArray];
[frasi addObject:secondArray];
NSMutableArray *array = [NSMutableArray arrayWithObjects:[frasi objectAtIndex:[button isSelected]], nil];
NSString *q = [array objectAtIndex: (arc4random()% [array count] )];
NSString *lab = [NSString stringWithFormat:#"%#", q];
self.label.text = lab;
all works, but the new label is
( "foo" )
instead of just foo (without quotes)... probably i mess in the last block of code...
ty
So, you create 2 mutable arrays, then add them to a new mutable array frasi. Then you get one of those two arrays and use it as the single element (because you use arrayWithObjects: instead of arrayWithArray:) of a new array array.
So array is an array that contains a single array element (instead of an array of strings as you may believe).
When you get an object from array, it's always the same single object that was used to initialize it: either firstArray or secondArray.
So you get an array of strings where you expect a string. When using stringWithFormat:, the specifier %# is replaced with the string description of that object.
A string returns itself as its own description. But the description of an array is the list of all its elements separated with commas and surrounded by parenthesis, which is why you get ( "foo" ).
So instead or creating unneeded arrays, you may just replace all the 8th last lines with this:
NSArray *array = [button isSelected] ? secondArray : firstArray;
self.label.text = [array objectAtIndex:arc4_uniform([array count])];
Actually u have array within array
Replace this line with yours:
NSString *q = [[array objectAtIndex: (arc4random()% [array count] )] objectAtIndex:0];

Getting an NSString out of an NSArray

I am trying to save and read back some application settings stored as NSStrings in an iPhone app and have been having some trouble.
The code to save looks like:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:accountID];
...
[array writeToFile:[self dataFilePath] atomically:YES];
[array release];
And the code to read looks like (accountID is an NSString*):
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
accountID = [array objectAtIndex:0];
...
[array release];
NSLog(#"Loading settings for: %#", accountID);
The read code throws an exception because after the array is released the accountID variable also appears to have been released (moving the NSLog call before releasing the array works fine). So I'm guessing that I'm creating a reference to the array instead of pulling out the actual string contained in the array. I tried several things to create new strings using the array contents but haven't had any luck.
You guess is on the right lines although you have a reference to the 0th element of the array not the array. The array consists of pointers to NSString objects. The Strings will get get released when yhe array is released.
You need to retain the element you are using e/g/
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
NSString* accountID = [[array objectAtIndex:0]retain];
...
[array release];
NSLog(#"Loading settings for: %#", accountID);
When you release the array the reference to the accountID will also be released. You need to retain it.
accountID = [[array objectAtIndex:0] retain];
Then obviously at some point you need to release it.
try [accountID retain] before you release the array

NSArray filled with bool

I am trying to create an NSArray of bool values. How many I do this please?
NSArray *array = [[NSArray alloc] init];
array[0] = YES;
this does not work for me.
Thanks
NSArrays are not c-arrays. You cant access the values of an NSArray with array[foo];
But you can use c type arrays inside objective-C without problems.
The Objective-C approach would be:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithBool:YES]];
//or
[array addObject:#(NO)];
...
BOOL b = [[array objectAtIndex:0] boolValue];
....
[array release];
EDIT: New versions of clang, the now standard compiler for objective-c, understand Object subscripting. When you use a new version of clang you will be able to use array[0] = #YES
Seems like you've confused c array with objc NSArray. NSArray is more like a list in Java, into which you can add objects, but not values like NSInteger, BOOL, double etc. If you wish to store such values in an NSArray, you first need to create a mutable array:
NSMutableArray* array = [[NSMutableArray alloc] init];
And then add proper object to it (in this case we'll use NSNumber to store your BOOL value):
[array addObject:[NSNumber numberWithBool:yourBoolValue]];
And that's pretty much it! If you wish to access the bool value, just call:
BOOL yourBoolValue = [[array objectAtIndex:0] boolValue];
Cheers,
Pawel
Use [NSNumber numberWithBool: YES] to get an object you can put in the collection.