This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to remove from NSMutableArray while iterating?
Mods: I realized this was a duplicate of this question, can you close/delete it?
If you don't want to create a temporary or new array, you can use this:
NSMutableArray *array = ...; // your mutable array
NSIndexSet *toBeRemoved = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
// The block is called for each object in the array.
BOOL removeIt = ...; // YES if the element should be removed and NO otherwise
return removeIt;
}];
[array removeObjectsAtIndexes:toBeRemoved];
(But a temporary NSIndexSet is used.)
Remark: My thought was that it might be more efficient to remove all matching elements "at once" instead of removing each element separately during the iteration, as suggested by Richard J. Ross III.
But a short test showed that this is not the case. Removing every second element from an array with 1000000 elements takes almost the same time with both methods on my computer.
You can use an NSPredicate to do this, see this SO question and answer.
https://stackoverflow.com/a/129942/36984
And the Apple docs for this:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/occ/instm/NSMutableArray/filterUsingPredicate:
Related
This question already has answers here:
NSArray of weak references (__unsafe_unretained) to objects under ARC
(12 answers)
Closed 7 years ago.
So in the following example, is it possible to cast the parameter in some way, to make it weak or something ?
-(void)addObject:(NSObject *)object {
[self.collection addObject:object];
}
By doing this, you would surely need to inspect each object you pull of the 'self.collection', to check to see if it is a dangling pointer, right ?
I don't know is that answer to your question but there is an class call NSHashTable that can hold weak references to its members.
You should have a look on it. You initialise it withe the option:
NSHashTable *hashTable = [NSHashTable hashTableWithOptions:NSHashTableWeakMemory];
The other options are:
NSHashTableStrongMemory
NSHashTableCopyIn
NSHashTableObjectPointerPersonality
And you use it in very similar way than NSArray but it's general purpose analogue of NSSet so maybe it's not good for you if you want to store non unique objects:
[hashTable addObject:#"myObj1"];
[hashTable addObject:#"myObj2"];
[hashTable removeObject:#"myObj2"];
I don't think you can stop weak reference with NSArray but the other option would be to wrap an object in value and stored the values instead:
NSValue *val = [NSValue valueWithNonretainedObject:#"myObj1"];
[array addObject:val];
I am trying to check if the NSMutableArray has a specific object, before adding the object to it, if exists then don't add.
i looked over many posts explaining how to do this, managed to implement it like this, but it always gives me that the object "doesn't exist", though i already added it !
//get row details into FieldLables Object
AllItemsFieldNames *FieldLabels = feedItems[row];
// object to hold single row detailes
AllItemsFieldNames *SelectedRowDetails = [[AllItemsFieldNames alloc] init];
SelectedRowDetails.item_name = FieldLabels.item_name;
//SelectedRowDetails.item_img = FieldLabels.item_img;
SelectedRowDetails.item_price = FieldLabels.item_price;
//NSLog(#"item has been added %#", SelectedRowDetails.item_name);
//NSLog(#"shopcartLength %lu", (unsigned long)SelectedFieldsNames.count);
if([SelectedFieldsNames containsObject:SelectedRowDetails])
{
NSLog(#"Already Exists!");
}
else
{
NSLog(#"Doesn't Exist!");
[SelectedFieldsNames addObject:SelectedRowDetails];
}
I can display all object from the NSMutableArray into a table, what i need to do in the above code is stop the addition of duplicate objects.
The first method listed on the NSArray documentation under the section "querying an array" is containsObject:. If it's not working, that suggests that your implementation of isEqual: is not correct. Make sure you follow the note in the documentation:
If two objects are equal, they must have the same hash value. This
last point is particularly important if you define isEqual: in a
subclass and intend to put instances of that subclass into a
collection. Make sure you also define hash in your subclass.
You might also consider using an NSSet since you can't add duplicates to that. Of course, this would also require a working version of isEqual:.
Sets are composed of unique elements, so this serves as a convenient way to remove all duplicates in an array.
here some sample,
NSMutableArray*array=[[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4", nil];
[array addObject:#"4"];
NSMutableSet*chk=[[NSMutableSet alloc ]initWithArray:array]; //finally initialize NSMutableArray to NSMutableSet
array= [[NSMutableArray alloc] initWithArray:[[chk allObjects] sortedArrayUsingSelector:#selector(compare:)]]; //after assign NSMutableSet to your NSMutableArray and sort your array,because sets are unordered.
NSLog(#"%#",array);//1,2,3,4
This question already has answers here:
Random number without repeating
(3 answers)
Closed 8 years ago.
I'm brand new to SpriteKit, and I'm creating a game that involves randomizing the CGPoint positions of objects on my screen when the user reaches certain score increments. I created a plist of the 8 set positions I want my objects to choose from when this method is called, but I'm having a problem with my objects selecting duplicate plist positions and overlapping each other. Is there a method I can call that will prevent my objects from picking the same position from the plist as another object when that method is called?
FYI, I plan on calling this randomization method many times throughout the course of the game.
I wrote the following code but my game crashes.
- (NSMutableArray *)pickAndRemoveFromList:(NSMutableArray *)list {
list = [_objectList copy];
NSInteger randomIndex = arc4random()%list.count;
Objects *object = [list objectAtIndex:randomIndex];
[list addObject:object];
[list removeObject:object];
return list;
}
Your method has several problems. First, you're passing in a mutable array called list, but then in the first line of the method you redefine what list is. You either shouldn't pass in the list to start with, or you shouldn't redefine it. Second, if _objectList is an immutable array, you need to use mutableCopy to make it a mutable array, not copy. Third, there's no need to add an object to the list, and then turn around and remove it in the next line. Also a better random number function to use is arc4random_uniform(). So, if you're passing in a mutable array, your method should be,
- (NSMutableArray *)pickAndRemoveFromList:(NSMutableArray *)list {
NSInteger randomIndex = arc4random_uniform((int)list.count);
Objects *object = [list objectAtIndex:randomIndex];
[list removeObject:object];
return list;
}
It is a simple pull to refresh case. I have data loaded into table and have a mutable data array at back-end, I receive a array of new data and want to add this complete array at start of existing array.
One workaround is to create new array with new arrived data and then add previous array into it using addObjectsFromArray: method. Is there some workaround to add new data array to the start of previous array directly?
First, build an NSIndexSet.
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:
NSMakeRange(0,[newArray count])];
Now, make use of NSMutableArray's insertObjects:atIndexes:.
[oldArray insertObjects:newArray atIndexes:indexes];
Alternatively, there's this approach:
oldArray = [[newArray arrayByAddingObjectsFromArray:oldArray] mutableCopy];
NSMutableArray offers the insertObjects:atIndexes: method, but it's easier to append the way you suggest using addObjectsFromArray:.
-insertObject:atIndexes: is easy enough, and should (I believe) be more efficient than using -addObjects and swapping arrays. It'd probably end up looking something like this:
[existingResults addObjects:newResults atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, newResults.count)]]`
Creating a new array is probably your best solution, but you can also use a loop
NSUInteger index;
index = 0;
for ( id item in sourceArray )
{
[destArray insertObject:item atIndex:index];
index++;
}
Just simple way:
NSMutableArray *arrayTmp = [firstArr addObjectsFromArray:myArray];
myArray = arrayTmp;
I have a NSMutableArray that i define in the header file as:
#property (strong, nonatomic) NSMutableArray *tempPhotosArray;
Then i allocate as:
_tempPhotosArray = [[NSMutableArray alloc] init];
What i'd like to know is if i then go to replaceObjectAtIndex the program will complain on an out of bounds. I want to keep only a set number of items in that array, so is it possible to do a insert or replace? i.e. if at index 0 it is empty do an insert, if there is an object already replace it?
Thanks
i think i agree with Hani Ibrahim. Since you said you only want to keep a set number of objects in the array. So how many you want?
// add these code when you initialize the array
int aSetNumber = 5;
_tempPhotosArray = [[NSMutableArray alloc] init];
for (int i = 0; i < aSetNumber; i++)
{
[_tempPhotosArray addobject: [NSNull null]];
}
i guess then you can do whatever you want, i don't know what exactly you want to do in this case, but i would check if the object in that position is NSNUll, if so, replace that, if not, i don't know what you want them
//use these code when you trying to insert the real object
if([[_tempPhotoArray objectAtIndex:anIndex] isKindOfClass: [NSNull class]])
{
//replace it here
}
As to why you are getting an error, what everyone else wrote is accurate, but....
The description of what you want doesn't match what an NSArray is. It sounds like you want a list of up to 5 items and never more than 5. It might be that if you try to add a 6th item the "oldest" goes away. Like a "recently opened" file history. You can make this type of functionality with an NSArray, but that's not what it is out of the box.
I would suggest making your own object class. I'm not going to write all the code for you, because this sounds suspiciously like programming homework, but I will point you in the correct direction.
FivePack <-- our class
NSArray *storage; <-- where we house the data
// a public method which lets you add things.
- (void)addItem:(id)item {
int indexOfLastItemInArrayToSave = 4;
if (storage.length < 4)
indexOfLastItemInArrayToSave = length-1;
NSRange range = NSMakeRange(0, indexOfLastItemInArrayToSave);
NSArray *temp = [storage subArrayWithRange:range];
// now create a new array with the first item being "item" that
// was passed in and the rest of the array being the contents of temp.
// Then save that to storage.
}
What you want to do with the data and writing something to get it from your new object is up to you, because I'm not sure how you want to do it.
There are no objects in the array when you initially created it, so there is nothing to replace.
Like this?
if([_tempPhotosArray count] > 0)
//replace object
else
//add object to array