This question already has answers here:
How to remove all objects with the same property value but one in NSMutableArray
(3 answers)
Closed 9 years ago.
I have one NSObject with properties as following
#property (nonatomic, retain) NSString * destinationid;
#property (nonatomic, retain) NSString * destinationname;
#property (nonatomic, retain) NSString * assetid;
#property (nonatomic, retain) NSString * assetname;
#property (nonatomic, retain) NSString * assetdescription;
Here, I save this in NSMutableArray.
The data which I get from server contains same DestinationName, but different other properties.
I want to check, if same name of Object is already added to NSMutableArray, don't add it again.
I tried to user innner loops but no use :(
Thanks
Here's one solution:
NSArray *originalArray = ... // original array of objects with duplicates
NSMutableArray *uniqueArray = [NSMutableArray array];
NSMutableSet *names = [NSMutableSet set];
for (id obj in originalArray) {
NSString *destinationName = [obj destinationname];
if (![names containsObject:destinationName]) {
[uniqueArray addObject:obj];
[names addObject:destinationName];
}
}
One way to do it is to create a new array that only contains the destination names from your other array, and check if the name from your server is contained there:
NSArray *names = [self.mut valueForKey:#"destinationname"];
if (![names containsObject:destName]) {
[self.mut addObject:newObjectFromServer];
}
mut is the name of my mutable array, and destName is the destination name in the object your getting from the server.
This function should do the job:
BOOL contains(id object, NSMutableArray *array)
{
for (id array in yourArray)
if ([object.destinationname isEqualToString:yourObject.destinationname])
return YES;
return NO;
}
Usage example:
if (!contains(object, array))
[array addObject:object];
Related
I create the custom class name with FileModel.
FileModel.h
#import <Foundation/Foundation.h>
#interface FileModel : NSObject
#property (nonatomic, copy) NSString *fileName;
#property (nonatomic, copy) NSString *fileType;
#property (nonatomic, strong) NSDate *editDate;
#property (nonatomic, assign) NSInteger fileSize;
#end
I want to compare the particular string with the fileName.
I create the sample like below .m
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *fileSampleName = [[NSArray alloc] initWithObjects:#"apple.png",#"banana.png",#"cherry.png",#"durian.png",#"grape.png",#"avocado.png", nil];
NSMutableArray *fileData = [NSMutableArray new];
FileModel *fileModel = nil;
for( NSInteger i = 0 ; i < fileSampleName.count ; i++){
fileModel = [FileModel new];
fileModel.fileName = [fileSampleName objectAtIndex:i];
fileModel.fileType = #"photo";
fileModel.fileSize = 0;
fileModel.editDate = [NSDate new];
[fileData addObject:fileModel];
}
// fileData's fileName containsObject #"grape" or not?
}
NSArray has containsObject method.
But How can I check the #"grape" is containsObject using fileData at the custom class property filename?
I known using for loop compare one by one.
Did they have other method to check like containsObject?
--- edit---
I try to using indexOfObjectPassingTest method , But the result always is 1.
BOOL result = [fileData indexOfObjectPassingTest:^ BOOL (id tr,NSUInteger index, BOOL *te){
FileModel *fileModel = (FileModel*)tr;
if([#"orange" isEqualToString: fileModel.fileName]){
*te = YES;
return YES;
}else{
return NO;
}}];
NSLog(#"result:%#",#(result)); // it always return 1
Why? thank you very much.
Take a look that NSArray class reference in Xcode. One method you could use is indexOfObjectPassingTest. There are number of related methods depending on your needs. All take a block that's used to test objects to see if they meet whatever criteria you want. In your case you'd test the fileName string.
So you'd pass in a closure that compared the fileName property of each object to your desired filename.
It's a custom class:
#import <Foundation/Foundation.h>
#interface timeTable : NSObject
#property (nonatomic) int ID;
#property (nonatomic) NSString * type;
#property (nonatomic) NSString * time;
#property (nonatomic) NSString * busno;
#property (nonatomic) NSString * stops;
// nothing is done in it's .m file not even synthesise
// thats an other class
#import <Foundation/Foundation.h>
#import "timeTable.h"
#interface refreshDatabase : NSObject
#property (strong, nonatomic) NSMutableArray * arrayTimeTable;
#property (strong, nonatomic) timeTable * objectTimeTable;
// in it's .m file i am downloading a JSON formatted array using a
service then i am saving it to NsMutbaleArray
// downloading a json array which contains a rows of data
NSError * error;
NSArray * jsonArray = [NSJSONSerialization JSONObjectWithData:
[safeString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingAllowFragments error:&error];
NSLog(#"json Array %#", jsonArray);
// for getting an instance of array
NSDictionary * jsonElement;
for (int i=0; i<jsonArray.count ; i++)
{ // each row will be saved in an object of timetable class then that
// object will be saved to nsmutablearray
jsonElement = [jsonArray objectAtIndex:i];
objectTimeTable = [[timeTable alloc]init];
objectTimeTable.ID = [[jsonElement objectForKey:#"id"]intValue];
objectTimeTable.type = [jsonElement objectForKey:#"type"];
objectTimeTable.time = [jsonElement objectForKey:#"time"];
objectTimeTable.busno = [jsonElement objectForKey:#"busno"];
objectTimeTable.stops = [jsonElement objectForKey:#"stops"];
// adding an instance from JSON Array to our NSmutablearray
[arrayTimeTable addObject:objectTimeTable];
}//end of json Array FOR loop
// our array containnig all the objects will be saved using
//NSUserDefualts
// userDefaults is an object of NSUserDefaults
if(userDefaults)
{ // its not saving it to userdefaults
[userDefaults setObject:arrayToStore forKey:#"ArrayOfTimeTables"];
[userDefaults synchronize];
}
// retrieving the saved array from NSUSerDefaults and printing it
// using slog
timeTable *objPrint = [[timeTable alloc]init];
NSMutableArray *arrayLoader = [userDefaults arrayForKey:#"ArrayOfTimeTables"];
for (int i=0; i<arrayLoader.count ; i++)
{
objPrint = [arrayLoader objectAtIndex:i];
NSLog(#"outSide Printing For LOOP After Loading of tim # %d times havind id =%d type = %# time = %# busno = %# stops = %#",i,objPrint.ID,objPrint.type,objPrint.time,objPrint.busno,objPrint.stops);
}
Thanx a lot in helping me in advance.
Please tell me how to save that array which contains object of timetable class into nsUseDefaults and then how to load it back.
Please help me. I read a lot of similar question and answers, but don't know how to make them work for me.
Use NScoding to encode each of your custom object then add that custom object into an array then encode other and then add it to the array then save that array into NSUserDefaults
encoding and decoding of upper given question
is
the custom class .h file
#import <Foundation/Foundation.h>
#interface timeTable : NSObject<NSCoding>
#property (nonatomic) NSString * ID;
#property (nonatomic) NSString * type;
#property (nonatomic) NSString * time;
#property (nonatomic) NSString * busno;
#property (nonatomic) NSString * stops;
the custom class .m file
#import "timeTable.h"
#implementation timeTable
#synthesize ID;
#synthesize type;
#synthesize time;
#synthesize busno;
#synthesize stops;
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.ID forKey:#"ID"];
[aCoder encodeObject:self.type forKey:#"type"];
[aCoder encodeObject:self.time forKey:#"time"];
[aCoder encodeObject:self.busno forKey:#"busno"];
[aCoder encodeObject:self.stops forKey:#"stops"];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if((self = [super init])) {
//decode properties, other class vars
self.ID = [aDecoder decodeObjectForKey:#"ID"];
self.type = [aDecoder decodeObjectForKey:#"type"];
self.time = [aDecoder decodeObjectForKey:#"time"];
self.busno = [aDecoder decodeObjectForKey:#"busno"];
self.stops = [aDecoder decodeObjectForKey:#"stops"];
}
return self;
}
#end
where you encode each custom object one by one and adding it to the array then save that NSMutableArray or NSArray
into NSUserDefaults
encoding a custom object then adding it to array and saving it into user defaults
// encoding a custom object before saving it to array
NSData *encodeTimeTableObj = [NSKeyedArchiver
archivedDataWithRootObject:objectTimeTable];
addObject:encodeTimeTableObj];
//saving it to user Defaults
if(userDefaults)
{
[userDefaults setObject:arrayTimeTable
forKey:#"ArrayOfTimeTables"];
[userDefaults synchronize];
NSLog(#"saving to usedefaults");
}
retriving an array either mutable or non mutable then decoding each of its object
NSMutableArray *arrayLoader = [userDefaults
objectForKey:#"ArrayOfTimeTables"];
NSData * decode = [arrayLoader objectAtIndex:0];
// in case of upper given custom class Time Table
timeTable *objPrint = [NSKeyedUnarchiver unarchiveObjectWithData:decode];
Use NSArray to get array from NSUSerDefaults as NSUSerDefaults return immuttable array.
If you need NSMutableArray, then convert this NSArray to NSMutableArray.
// retrieving the saved array from NSUSerDefaults and printing it
// using slog
timeTable *objPrint = [[timeTable alloc]init];
NSArray *arrayLoader = [userDefaults arrayForKey:#"ArrayOfTimeTables"];
for (int i=0; i
I have an NSArray called carparkArr that contain MyCarpark objects. This class contain:
#property (nonatomic, assign) CLLocationCoordinate locationCoord;
Now I want to create an array that will have NSValue of each of these objects. How to do it quickly? I want something like:
NSArray *carparkArr = // fetching data
NSArray *locationProperty = [self getArrayForPropertyPath:#".locationCoord" forArray:carparkArr];
Yeah that feature already exists:
NSArray *locationProperty = [carparkArr valueForKey:#"locationCoord"];
This question already has answers here:
objects conforming to nscoding will not writetofile
(2 answers)
Closed 8 years ago.
I would like to have an array of model and a field of this model is a mutable array.
Let's say, for example ,in my Model.h I have :
#interface myModel : NSObject
#property (assign,nonatomic) NSString* name;
#property (assign,nonatomic) NSString* time;
#property (assign,nonatomic) NSMutableArray * songs;
#end
then my view controller I have:
NSMutableArray * Storage;
myModel * arr;
arr =[[alarmModel alloc] init];
arr.name=#"pippo";
arr.time=#"01:00:00";
arr.songs=[NSMutableArray arrayWithObjects:#"pippo",#"pluto",#"paperino", nil];
[storage addObject:arr];
[storage writeToFile:filePath atomically:YES]
the last command return "NO" it means that write to file failed.
Is it possible to do what I want to do?
you should init your NSMutableArray *storage, try:
NSMutableArray *storage = [[NSMutableArray alloc] init];
I know that subtracting an NSArray from NSArray if it is a single basic object found here
But what i have is an object like this
#interface Set : NSObject
#property (nonatomic, strong) NSString *ItemId;
#property (nonatomic, strong) NSString *time;
#property (nonatomic, strong) NSString *Category_id;
#property (nonatomic, strong) NSString *List_id;
#property (nonatomic, strong) NSString *name;
#end
How can i delete an array having the set object from another array with the same?
It can be done by iterations that i knw.Is there some other way ?
EDIT: For clarity
I have Array A with 5 Set objects and I have 4 Set Objects in Array B
array A and Array B contain 3 set objects with common values..[Note : memory may be different] common
All I need is an Array C =Array A - Array B that has 2 objects in resulting array C
Thank You :)
You need to implement the - (NSUInteger)hash and - (BOOL)isEqual:(id)object method in Set class.
For eg:-
- (NSUInteger)hash {
return [self.ItemId hash];
}
- (BOOL)isEqual:(id)object
{
return ([object isKindOfClass:[self class]] &&
[[object ItemId] isEqual:_ItemId])
}
After that try this:
NSMutableSet *set1 = [NSMutableSet setWithArray:array1];
NSMutableSet *set2 = [NSMutableSet setWithArray:array2];
[set1 intersectSet:set2]; //this will give you only the obejcts that are in both sets
NSArray *commonItems = [set1 allObjects];
[mutableArray1 removeObjectsInArray:commonItems];//mutableArray1 is the mutable copy of array1
mutableArray1 will have all objects in the same order as earlier after removing common objects.
By using NSSet and NSPredicate we can meet your requirement.
Assessors *ass1 = [[Assessors alloc] init];
ass1.AssessorID = #"3";
Assessors *ass2 = [[Assessors alloc] init];
ass2.AssessorID = #"2";
Assessors *ass3 = [[Assessors alloc] init];
ass3.AssessorID = #"1";
Assessors *ass4 = [[Assessors alloc] init];
ass4.AssessorID = #"2";
NSSet *nsset1 = [NSSet setWithObjects:ass1, ass2, nil];
NSSet *nsset2 = [NSSet setWithObjects:ass3, ass4, nil];
// retrieve the IDs of the objects in nsset2
NSSet *nsset2_ids = [nsset2 valueForKey:#"AssessorID"];
// only keep the objects of nsset1 whose 'id' are not in nsset2_ids
NSSet *nsset1_minus_nsset2 = [nsset1 filteredSetUsingPredicate:[NSPredicate predicateWithFormat:#"NOT AssessorID IN %#",nsset2_ids]];
for(Assessors *a in nsset1_minus_nsset2)
NSLog(#"Unique ID : %#",a.AssessorID);
Here Assessors is my NSObject Class (Set in your case) and AssessorID is one property of that class.
Hope this can help.