I made the following method to remove doubles, however it doesn't fully work. Any suggestions?
Thank you for the help,
-(NSMutableArray*)removeDuplicateCars:(NSMutableArray*)array{
NSMutableArray *noDuplicates =[[NSMutableArray alloc]init];
for (int i=0; i<[array count]; i++) {
int counter =0;
Car *car =(Car*)[array objectAtIndex:i];
if ([noDuplicates count]==0) {
[noDuplicates addObject:car];
}
for (int i=0; i<[noDuplicates count]; i++) {
Car *car2 =(Car*)[array objectAtIndex:i];
if (![car.name isEqualToString:car2.name]) {
counter++;
}
}
if (counter==[noDuplicates count]) {
[noDuplicates addObject:car];
}
}
NSLog(#"number of results = %i",[noDuplicates count]);
return noDuplicates;
}
Create an array called "addedCars" - you will use it to store the name of each unique car.
In each iteration, use [NSArray containsObject:] to check if the current name has already been added to "addedCars". If not, add the name to "addedCars" and the car to "noDuplicates". Otherwise, skip this item, as it has already been added to noDuplicates.
be sure [isEqual:] and [hash] is implemented as you expected
-(NSMutableArray*)removeDuplicateCars:(NSMutableArray*)array{
NSOrderedSet *set = [[NSOrderedSet alloc] initWithArray:array];
NSMutableArray *newArr = [NSMutableArray arrayWithCapacity:[set count]];
for (id obj in set) {
[newArr addObject:obj];
}
return newArr;
}
You used ![car.name isEqualToString:car2.name] to compare objects so I believe you want to filter objects with same name? Than you need to override [isEqual:] for Car
- (BOOL)isEqual:(id)other {
if ([other isKindOfClass:[self class]]) {
return [self.name isEuqalToString: [other name]];
}
return NO;
}
- (NSUInteger)hash {
return [self.name hash];
}
also check this question The best way to remove duplicate values from NSMutableArray in Objective-C?
Related
I am adding NSInteger object as NSNumber in a NSMutableArray. But now I am such in condition like that I need to check a NSInteger is in the NSMutableArray. If the array contains the value then I will execute my next code else I will execute other code. I want to execute else condition only if array doesn't contain the value. I tried this code:
for(int i=0; i<self.indexArray.count; i++){
if([[self.indexArray objectAtIndex:i] integerValue]==self.selectedIndex){
NSLog(#"execute if in the array");
}
else{
NSLog(#"execute if not in the array");
}
}
Though the array contains the value, else is executing for the loop. My question is how will I check a value which one is in a NSMutableArray or not.
This is the simple solution:
BOOL containsSelected = NO;
for (int i = 0; i < self.indexArray.count; i++){
if ([[self.indexArray objectAtIndex:i] integerValue] == self.selectedIndex){
containsSelected = YES;
break;
}
}
if (containsSelected) {
NSLog(#"execute if in the array");
} else {
NSLog(#"execute if not in the array");
}
I believe this could be further simplifed to:
if ([self.indexArray containsObject:#(self.selectedIndex)]) {
NSLog(#"execute if in the array");
} else {
NSLog(#"execute if not in the array");
}
but I haven't tested it.
I am sorting an array.
There are three types of elements in the array.
1. featured
2. organic and
3. claimed.
Among them, I want to sort only organic elements and keep the featured and claimed elements at their own index.
Below is my code in which, I am extracting the claimed and featured indices in a dictionary as key being the index and value is the array element.
//Initialization
NSMutableArray *sortedArray = nil;
NSMutableDictionary *tempFeaturedDictionary = [[NSMutableDictionary alloc]init];
NSMutableDictionary *tempClaimedDictionary = [[NSMutableDictionary alloc]init];
NSMutableArray *tempOrganicArray = [[NSMutableArray alloc]init];
for (int i = 0; i < array.count; i++) {
DRListing *isFeaturedObj = (DRListing*)[array objectAtIndex:i];
if (isFeaturedObj.featured) {
[tempFeaturedDictionary setObject:isFeaturedObj forKey:[#(i)stringValue]];
}else if (isFeaturedObj.claimed)
{
[tempClaimedDictionary setObject:isFeaturedObj forKey:[#(i)stringValue]];
}else
[tempOrganicArray addObject:isFeaturedObj];
}
Again I am adding the claimed and featured back to their original indices after sorting as:
sortedArray = [NSMutableArray arrayWithArray:[tempOrganicArray sortedArrayUsingDescriptors:sortDescriptorsArray]];
for (int i = 0; i<sortedArray.count; i++) {
for (NSString *key in tempFeaturedDictionary) {
if ( [[#(i)stringValue] isEqualToString: key] ) {
[sortedArray insertObject:[tempFeaturedDictionary objectForKey:[#(i)stringValue]] atIndex:i];
}}
for (NSString *key in tempClaimedDictionary) {
if ([[#(i)stringValue]isEqualToString:key ]) {
[sortedArray insertObject:[tempClaimedDictionary objectForKey:[#(i)stringValue]] atIndex:i];
}
}
}
The code works good. Except there is claimed/(and)featured elements at the last index of the 'array'. Because the 'sortedArray' index remains less than the 'array.count' in this scenario.
Thanks in advance.
Update -
I receive response array of type:
[{featured1 featured2}, {organic1, organic2..}, {claimed1}, {featured11, featured12}, {organic11, organic12..}, {claimed2}, ..]
and I am allowed to sort only organic elements within this array. Featured and claimed should not loose their original index position.
I would iterate through the array, extracting the organics to sort. Then sort your organic array. Then iterate through the original array taking either the element from the original array or an element from the sorted organics array as appropriate.
NSMutableArray *organicsArray = [NSMutableArray new];
for (int i = 0; i < array.count; i++) {
DRListing *isFeaturedObj = (DRListing*)array[i];
if ((!isFeaturedObj.featured) && (!isFeaturedObj.claimed)) {
[organicsArray addObject:isFeaturedObj];
}
}
NSMutableArray *sortedOrganicsArray = [[organicsArray sortedArrayUsingDescriptors:sortDescriptorsArray] mutableCopy];
NSMutableArray *outputArray = [NSMutableArray new];
for (int i = 0; i < array.count; i++) {
DRListing *isFeaturedObj = (DRListing*)array[i];
if ((!isFeaturedObj.featured) && (!isFeaturedObj.claimed)) {
[outputArray addObject:sortedOrganicsArray[0]];
[sortedOrganicsArray removeObjectAtIndex:0];
} else {
[outputArray addObject:isFeaturedObject];
}
}
You could possibly make it a little more efficient if you reversed your sort order for the organics array since then you could say
[outputArray addObject:[sortedOrganicsArray lastObject]];
[sortedOrganicsArray removeLastObject];
But if your array isn't particularly large then the performance improvement will probably be negligible.
Maybe this is an alternative:
NSMutableArray *organics = [NSMutableArray new];
NSMutableArray *others = [NSMutableArray new];
for (DRListing *isFeaturedObj in array) {
if (isFeaturedObj.organic) {
[organics addObject:isFeaturedObj];
} else {
[others addObject:isFeaturedObj];
}
}
NSMutableArray *sorted = [NSMutableArray alloc]initWithObjects:organics,others, nil];
You can take the first 2 functions. The others are what I used for testing.
- (DRListing *)getNextObjectFromArray:(NSArray *)array WithStartingIndex:(int)index
{
for (int i=index; i<array.count; i++) {
DRListing *obj = (DRListing*)[array objectAtIndex:i];
if (!obj.featured && !obj.claimed)
{
return obj;
}
}
return nil;
}
- (void)sortArray:(NSMutableArray *)array
{
for (int pass = 0; pass<array.count-1; pass++) {
for (int i=0; i<array.count-1; i++) {
DRListing *obj = [self getNextObjectFromArray:array WithStartingIndex:i];
int foundIndex = (int)[array indexOfObject:obj];
DRListing *obj2 = [self getNextObjectFromArray:array WithStartingIndex:foundIndex+1];
int foundIndex2 = (int)[array indexOfObject:obj2];
if (obj!=nil && obj2 !=nil) {
if (obj.value >= obj2.value) {
[array exchangeObjectAtIndex:foundIndex withObjectAtIndex:foundIndex2];
}
i = foundIndex;
}
}
}
NSLog(#"Sorted Data: %#",array);
}
- (NSMutableArray *)testData
{
NSMutableArray *array = [NSMutableArray new];
for (int i=0; i<20; i++) {
DRListing *obj = [DRListing new];
obj.featured = i*i%2;
obj.claimed = i%2;
obj.value = i*3%10;
[array addObject:obj];
}
NSLog(#"Test Data: %#",array);
return array;
}
#interface DRListing : NSObject
#property (nonatomic) BOOL featured;
#property (nonatomic) BOOL claimed;
#property (nonatomic) int value;
#end
First off i have searched a lot but all methods seems to be for primitives or for whole custom objects.
My situation is this. I have a type custom objects in two different arrays. However the fields of every single objects is quite different to another with the exception of only 2 fields.
What i want is combine both of these arrays and then remove duplicates with respect to only those two fields.How can i do that. My Code so far
NSMutableArray* testArray = [eventHandler returnAllEvents];
NSMutableArray* combinedArray = [[NSMutableArray alloc]init];
NSArray* finalArray = [[NSArray alloc]init];
if (testArray.count==0) {
for (int i = 0; i<facebookData.count; i++) {
LSEvent* event = [facebookData objectAtIndex:i];
[combinedArray addObject:event];
}
finalArray = [combinedArray arrayByAddingObjectsFromArray:calendarData];
}
NSMutableArray *uniqueArray = [NSMutableArray array];
NSMutableSet *names = [NSMutableSet set];
for (id obj in finalArray) {
NSString *destinationName = [obj destinationname];
if (![names containsObject:destinationName]) {
[uniqueArray addObject:obj];
[names addObject:destinationName];
}
}
You can do sth like this
NSArray first = ...
NSMutableArray second = ... // this will be combine array
for (id someObj in first) {
if ( [second filteredArrayUsingPredicate:[self predicateForObject:someObj ]].count == 0 ){
[second addObject: someObj];
}
}
If you want to check that object exists in array using containsObject: you need to implement - (BOOL)isEqual:(id)other in your custom object.
- (BOOL)isEqual:(id)other {
if (other == self) {
return YES;
}
if (!other || ![other isKindOfClass:[self class]]) {
return NO;
}
if (self.identifier == other.identifier) {
return NO;
}
return YES;
}
I have an NSMutable array which i'm trying to remove objects from and by that to decrease
the count of number of objects on the array, and the count always stays the same,
Meaning, the remove is not working.
Here is the code (it's from the online stanford IOS development course):
- (NSMutableArray *)cards
{
if (!_cards) _cards = [[NSMutableArray alloc] init];
return _cards;
}
- (void)addCard:(Card *)card atTop:(BOOL)atTop
{
if (atTop) {
[self.cards insertObject:card atIndex:0];
} else {
[self.cards addObject:card];
}
}
- (void)addCard:(Card *)card
{
[self addCard:card atTop:NO];
}
- (Card *)drawRandomCard
{
Card* randomCard = Nil;
NSLog(#"This is the count %d",[self.cards count]);
if ([self.cards count]) {
unsigned index = arc4random() % [self.cards count];
randomCard = self.cards[index];
[self.cards removeObjectAtIndex:index];
}
return randomCard;
}
The count is always 52, even after removing the objects.
Any ideas on how to fix this?
I want to make 1 array that will hold all of the other arrays objects and will look like this
("052-6224754","03-6475075","02-6753231")
my code is:
-(NSMutableArray*) getRecepientsPhones
{
NSMutableArray* phones = [[NSMutableArray alloc]init];
//scroll all choosed contacts and retrieve phones to nsstring
if([recepientsFromContacts count]>0)
for (int i=0; i<[recepientsFromContacts count]; i++)
{
NSMutableArray* tempArray = [[NSMutableArray alloc]init];
if(![[[recepientsFromContacts objectAtIndex:i]objectForKey:#"CPhones"]isKindOfClass:[NSNull class]])
{
[tempArray addObject:[[recepientsFromContacts objectAtIndex:i]objectForKey:#"CPhones"]];
for(int j = 0; j<[tempArray count];j++)
{
[phones addObject:[tempArray objectAtIndex:j]];
}
}
}
//lets fetch from that contact
if([personRecepient count]>0)
{
if(![[personRecepient objectForKey:#"CellPhone"]isKindOfClass:[NSNull class]])
[phones addObject:[personRecepient objectForKey:#"CellPhone"]];
}
NSLog(#"%#",phones);
return phones;
}
[[recepientsFromContacts objectAtIndex:i]objectForKey:#"CPhones"]
is 1 or more dimension array (it is array of phone numbers per person , person can have more than 1 number)
example: ("052-6224754","03-6475075")
but my function returns
("052-6224754","03-6475075"),("02-6753231")
which is not good , what should I do to make it 1 array
("052-6224754","03-6475075","02-6753231")
You should change the line
[phones addObject:[tempArray objectAtIndex:j]];
to
[phones addObjectsFromArray:[tempArray objectAtIndex:j]];
This should result in a flattened array of phone numbers.
Then you should head over to codereview.stackexchange.com because there are several issues with your code fragment.
Edit: Here's a cleaned up version of the method:
- (NSArray *)recepientsPhoneNumbers
{
NSMutableArray* phoneNumbers = [NSMutableArray array];
for (NSDictionary *dict in _recepientsFromContacts)
{
id recipientPhoneNumbers = dict[#"CPhones"];
if (recipientPhoneNumbers != [NSNull null])
[phoneNumbers addObjectsFromArray:recipientPhoneNumbers];
}
id recipientPhoneNumbers = _personRecepient[#"CellPhone"];
if (recipientPhoneNumbers != [NSNull null])
[phoneNumbers addObjectsFromArray:recipientPhoneNumbers];
NSLog(#"%#", phoneNumbers);
return phoneNumbers;
}
I applied Cocoa coding conventions, so ivars are now prefixed with underscores.