Create array by comparing JSON data to an array - ios

I'm getting access to 'hotel' from json file:
NSArray *hotel = [jsonObject valueForKeyPath:#"location.hotel"];
With print out like (UPDATED):
<__NSCFArray 0x7b254d70>(
{
test = A;
hotel = (
{
luxuryHotels = hotel1;
},
{
luxuryHotels = hotel2;
},
I want to check if the array 'hotel' contains objects from another array 'myHotels' and if it does, create an array with only those objects.
NSArray *myHotels = [NSArray arrayWithArray:hotel.luxuryHotels];
NSMutableArray *hotel2 = [[NSMutableArray alloc] init];
for (NSArray *object in hotel) {
NSMutableSet *set1 = [NSMutableSet setWithArray: object];
NSSet *set2 = [NSSet setWithArray: myHotels];
[set1 intersectSet: set2];
NSArray *resultArray = [set1 allObjects];
NSLog(#"resultArray is %#",resultArray);
[hotel2 addObject:resultArray];
}
The print for 'hotel2' is something like: (
),( hyatt
),(
)
Is there a way to get a string of only hyatt? Or a way to combine the dictionaries of the array so it show as on list if there are more than one hotel listed?

It's still not 100% clear what the data structure looks like but you could try something like this
Collapse your initial data structure (array of arrays) into just an array, then convert this into a mutable set
NSArray *flattenedHotels = [jsonObject valueForKeyPath:#"#distinctUnionOfArrays.location.hotel"];
NSMutableSet *hotels = [NSMutableSet setWithArray:flattenedHotels];
Next you just perform an intersection with myHotels
[hotels intersectSet:[NSSet setWithArray:myHotels]];
NSArray *result = hotels.allObjects;

Related

NSPredicate to search an array with any objects from a list | Obj C

I have to sort/search an array of dictionaries based on an array of tag ids.
The web service send a list of articles which have tag ids like [1,2,3,5] for every article.
The user selects multiple tags from a list and there tag ids are stored in an array like [4,2,8,1]
** Now i have to compare the user selected tags with the article tags and if any tag in the 2 arrays match it is stored in a result array **
What should I use and How? NSPredicate or a NSSortdescriptor
In short i have to do something like this:
userTags = [4,6,2,1]
articleTags = [1,2,3,4,5]
if ANY [userTags] IN [articleTags]
[resultArr addObject:article]
I believe you should use NSSet for your task instead of NSArrays. And check if sets intersect, e.g.:
NSSet *tags = [NSSet setWithArray:#[#1, #3, #5]];
NSSet *article1 = [NSSet setWithArray:#[#2, #4, #6]];
NSSet *article2 = [NSSet setWithArray:#[#2, #3, #4]];
NSLog(#"%d", [tags intersectsSet:article1]);
// 0
NSLog(#"%d", [tags intersectsSet:article2]);
// 1
Mindaugas answer worked.
NSSet *selectedTagSet = [NSSet setWithArray:selectedTagIds];
NSMutableArray *result = [NSMutableArray array];
for (int i = 0; i < [self.responceArray count]; i++) {
NSMutableDictionary *dict = [self.responceArray objectAtIndex:i];
NSSet *tagSet = [NSSet setWithArray:[[dict objectForKey:#"seller"] objectForKey:#"tags"]];
if ([tagSet intersectsSet:selectedTagSet])
{
[result addObject:[self.responceArray objectAtIndex:i]];
}
}

Create an array of NSSet having values of distinct properties of an object present in another NSArray

I have an array having objects with different properties. I want to create an array of sets which contain objects with same value of a single property of the object.
Suppose this is an array of object which has property a and b
1: {a:10, b:5}, 2: {a:2,b:5}, 3: {a:20,b:5}, 4: {a:5,b:5}, 5: {a:4,b:20}, 6: {a:51,b:20}
I want to create another array of NSSet of objects with distinct values of property b
so the result would be the following Array of 2 NSSet
1: {a:10, b:5}, {a:2,b:5}, {a:20,b:5}, {a:5,b:5}
2: {a:4,b:20}, {a:51,b:20}
How can this be done?
I'd do this by first creating a dictionary of sets where the keys of the dictionary are the unique values of "b".
Note: This is untested code. There could be typos here.
NSArray *objectArray = ... // The array of "SomeObject" with the "a" and "b" values;
NSMutableDictionary *data = [NSMutableDictionary dictionary];
for (SomeObject *object in objectArray) {
id b = object.b;
NSMutableSet *bSet = data[b];
if (!bSet) {
bSet = [NSMutableSet set];
data[b] = bSet;
}
[bSet addObject:object];
}
NSArray *setArray = [data allValues];
setArray will contain your array of sets.
This codes also assumes you have a sane isEqual: and hash implementation on your SomeObject class.
This is how you can do this:
NSArray *data = #[#{#"a":#10, #"b":#5}, #{#"a":#2,#"b":#5}, #{#"a":#4,#"b":#20}, #{#"a":#51,#"b":#20}];
NSSet *bSet = [NSSet setWithArray: [data valueForKey: #"b"]];
NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity: bSet.count];
for (NSNumber *bValue in bSet) {
NSPredicate *anArrayFilterPredicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *aDictionaryData, NSDictionary *bindings) {
if ([aDictionaryData[#"b"] isEqual:bValue]) {
return YES;
}
return NO;
}];
NSArray *uniqueBValueArray = [data filteredArrayUsingPredicate:anArrayFilterPredicate];
[filteredArray addObject:uniqueBValueArray];
}
NSLog(#"filteredArray = %#", filteredArray);
Using Key-Value coding collection operators, we can get the array of distinct values for an object. Then you could easily compute the results you want.
In your case this could be done like this.
NSArray *arrayOfDistinctObjects = [array valueForKeyPath:#"#distinctUnionOfObjects.b"];
NSMutableArray *newSetArray = [NSMutableArray new];
for (id value in arrayOfDistinctObjects) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.b == %#", value];
NSArray *filterArray = [array filteredArrayUsingPredicate:predicate];
NSSet *newSet = [NSSet setWithArray:filterArray];
[newSetArray addObject:newSet];
}
where array is the array of objects on which you wanna operate.
arrayOfDistinctObjects gives you the array of distinct values for b.

Compare 2 arrays of strings

I got 2 arrays of strings:
NSArray * current = #[#"1", #"6", #"53"];
NSArray * new = #[#"1", #"626", #"53", #"13"];
I want to get number 6 in array, and numbers 626 and 13 in second array
(I want data that is in first array but there is not in second, and conversely)
NSMutableSet * newSet = [NSMutableSet setWithArray:new];
[newSet minusSet:[NSSet setWithArray:current ]];
NSArray * result1 = [NSArray arrayWithSet:newSet];
NSArray * result2 = ?
I not get it, I know that is very simple question, but I have no ideas
Your code contains a lot of syntax errors.
Please post actual code, I understand the issue you are talking about, that's why I'm posting this answer. Please post questions with valid code, else you won't get proper answer (Only get downvotes)
Use the following code:
NSArray *current = #[#"1", #"6", #"53"];
NSArray *newArr = #[#"1", #"626", #"53", #"13"];
NSMutableSet *newSet = [NSMutableSet setWithArray:newArr];
[newSet minusSet:[NSSet setWithArray:current]];
NSArray * result1 = [NSArray arrayWithObjects:[newSet allObjects],nil];
// result 1 will have 626 and 13
newSet = [NSMutableSet setWithArray:current];
[newSet minusSet:[NSSet setWithArray:newArr]];
NSArray * result2 = [NSArray arrayWithObjects:[newSet allObjects],nil];
// result 2 will have 6
// Create arrays of the IDs only
NSArray *notiCloudIDs = [notiCloud valueForKey:#"id"];
NSArray *notiLocIDs = [notiLoc valueForKey:#"id"];
// Turn the arrays into sets and intersect the two sets
NSMutableSet *notiCloudIDsSet = [NSMutableSet setWithArray:notiCloudIDs];
NSMutableSet *notiLocIDsSet = [NSMutableSet setWithArray:notiLocIDs];
[notiCloudIDsSet intersectSet:notiLocIDsSet];
// The IDs that are now in notiCloudIDsSet have been present in both arrays
NSLog(#"Duplicate IDs: %#", notiCloudIDsSet);
This will give you the common elements in the two. You can then delete the common elements from array1.

Split NSArray into sub-arrays based on NSDictionary key values

We have an app that calls a SOAP web service and retrieves a long list of XML, which the app then parses into an NSArray of NSDictionary objects. The NSArray contains a list of Rental Apartment information, each of which is stored into an NSDictionary.
The entire list may contain 10 different types of Apartments (i.e. 2-room, 3-room), and we need to split the NSArray into smaller NSArrays based on Room-Type, which has the key "roomType" in the NSDictionary objects.
Currently our algorithm is
Use [NSArray valueForKeyPath:#"#distinctUnionofObjects.room-type"]
to obtain a list of unique room-type values.
Loop through the list of unique room-type values
For each unique room-type value, use NSPredicate to retrieve matching items from the Original list
Our code is below (renamed for clarity):
NSArray *arrOriginal = ... ...; // Contains the Parsed XML list
NSMutableArray *marrApartmentsByRoomType = [NSMutableArray arrayWithCapacity:10];
NSMutableArray *arrRoomTypes = [arrOriginal valueForKeyPath:#"distinctUnionOfObjects.roomType"];
for(NSString *strRoomType in arrRoomTypes) {
NSPredicate *predicateRoomType = [NSPredicate predicateWithFormat:#"roomType=%#", strRoomType];
NSArray *arrApartmentsThatMatchRoomType = [arrOriginal filteredArrayUsingPredicate:predicateRoomType]; // TAKES A LONG TIME EACH LOOP-ROUND
[marrApartmentsByRoomType addObject:arrApartmentsThatMatchRoomType];
}
However, step 3 is taking a long time as the original list may contain large amount (>100,000) of items. It seems that NSPredicate goes through the entire list for each key value. Is there a more efficient way of splitting a large NSArray into smaller NSArrays, based on NSDictionary keys?
If the order of your splited Arrays is not important, i have a solution for you:
NSArray *arrOriginal;
NSMutableDictionary *grouped = [[NSMutableDictionary alloc] initWithCapacity:arrOriginal.count];
for (NSDictionary *dict in arrOriginal) {
id key = [dict valueForKey:#"roomType"];
NSMutableArray *tmp = [grouped objectForKey:key];
if (tmp == nil) {
tmp = [[NSMutableArray alloc] init];
[grouped setObject:tmp forKey:key];
}
[tmp addObject:dict];
}
NSMutableArray *marrApartmentsByRoomType = [grouped allValues];
This is quite performant
- (NSDictionary *)groupObjectsInArray:(NSArray *)array byKey:(id <NSCopying> (^)(id item))keyForItemBlock
{
NSMutableDictionary *groupedItems = [NSMutableDictionary new];
for (id item in array) {
id <NSCopying> key = keyForItemBlock(item);
NSParameterAssert(key);
NSMutableArray *arrayForKey = groupedItems[key];
if (arrayForKey == nil) {
arrayForKey = [NSMutableArray new];
groupedItems[key] = arrayForKey;
}
[arrayForKey addObject:item];
}
return groupedItems;
}
Improving #Jonathan answer
Converting array to dictionary
Maintaining the same order as it was in original array
//only to a take unique keys. (key order should be maintained)
NSMutableArray *aMutableArray = [[NSMutableArray alloc]init];
NSMutableDictionary *dictFromArray = [NSMutableDictionary dictionary];
for (NSDictionary *eachDict in arrOriginal) {
//Collecting all unique key in order of initial array
NSString *eachKey = [eachDict objectForKey:#"roomType"];
if (![aMutableArray containsObject:eachKey]) {
[aMutableArray addObject:eachKey];
}
NSMutableArray *tmp = [grouped objectForKey:key];
tmp = [dictFromArray objectForKey:eachKey];
if (!tmp) {
tmp = [NSMutableArray array];
[dictFromArray setObject:tmp forKey:eachKey];
}
[tmp addObject:eachDict];
}
//NSLog(#"dictFromArray %#",dictFromArray);
//NSLog(#"Unique Keys :: %#",aMutableArray);
//Converting from dictionary to array again...
self.finalArray = [[NSMutableArray alloc]init];
for (NSString *uniqueKey in aMutableArray) {
NSDictionary *aUniqueKeyDict = #{#"groupKey":uniqueKey,#"featureValues":[dictFromArray objectForKey:uniqueKey]};
[self.finalArray addObject:aUniqueKeyDict];
}
Hope, It will help when client wants final array in same order as input array.

How to create NSDictionary inside NSArray and How to access them in ios

I am new to iOS and want to create an NSArray like this which contains an NSDictionary.
[
{
Image: 1, 2,3
Title: 1,2,3
Subtitle:1,2,3
}
]
I have tried this.
NSArray *obj-image=#[#"Test.png",#"Test.png",#"Test.png"];
NSArray *obj-title=#[#"Test",#"Test",#"Test"];
NSArray *obj-subtitle=#[#"Test",#"Test",#"Test"];
NSDictionary * obj_dictionary ={ image : obj_image, title:obj_title, subtitle:obj_subtitle}
NSArray * obj_array= [obj_dictionarry];
But not working and how to access them.
First of all, you initialization of Arrays and Dictionaries is wrong. You cannot use "-" in the names, period.
Second, you need to allocate and then initialize the objects. This is how you do that with arrays:
NSArray *images = [NSArray arrayWithObjects: #"TestImage",#"TestImage",#"TestImage",nil];
NSArray *titles = [NSArray arrayWithObjects: #"TestTitle",#"TestTitle",#"TestTitle",nil];
NSArray *subtitles = [NSArray arrayWithObjects: #"TestSubTitle",#"TestSubTitle",#"TestSubTitle",nil];
Then you need Mutable dictionary and mutable arrays to work with the data (mutable means you can change the values inside, add or remove objects etc.)
This is the most basic example of what you are trying to achieve:
NSArray *images = [NSArray arrayWithObjects: #"TestImage",#"TestImage",#"TestImage",nil];
NSArray *titles = [NSArray arrayWithObjects: #"TestTitle",#"TestTitle",#"TestTitle",nil];
NSArray *subtitles = [NSArray arrayWithObjects: #"TestSubTitle",#"TestSubTitle",#"TestSubTitle",nil];
NSMutableArray *objectsMutable = [[NSMutableArray alloc] init];
for (NSString *string in images) {
NSMutableDictionary *dictMutable = [[NSMutableDictionary alloc] init];
[dictMutable setObject:string forKey:#"image"];
//determining the index of the image
NSInteger stringIndex = [images indexOfObject:string];
[dictMutable setObject:[titles objectAtIndex:stringIndex] forKey:#"title"];
[dictMutable setObject:[subtitles objectAtIndex:stringIndex] forKey:#"subtitle"];
NSDictionary *dict = [[NSDictionary alloc] init];
dict = dictMutable;
[objectsMutable addObject:dict];
}
NSArray *objects = objectsMutable;
NSLog(#"%#", objects);
Hope this helps.
As you can see, I'm going through the images array, capturing the index of each one, an then just apply values of other arrays from the same index into a mutable dictionary.
All I do after that is just make a regular dictionary and array to put the data inside. This is ho the Log will look:
(
{
image = TestImage;
subtitle = TestSubTitle;
title = TestTitle;
},
{
image = TestImage;
subtitle = TestSubTitle;
title = TestTitle;
},
{
image = TestImage;
subtitle = TestSubTitle;
title = TestTitle;
}
)
You have an array with three objects inside, each with their own image, title and subtitle.
Here is code :
NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableDictionary *mdict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"object1",#"key1",#"object2",#"key2",nil];
[array addObject:mDict];
so now if u need to access dictionary from array then :
NSMutableDictionary *mDict1 = [array objectatindex:0];
NSLog(#"%#",[mDict1 valueForkey:#"key1"];
--> print object 1.
This is the way to store array of dictionaries:
NSDictionary *dic=#{#"kishore":#"hai"};
NSMutableArray *arr=[[NSMutableArray alloc]init];
[arr addobject:dic];
this is the way to get those values:
[arr objectforkeyValue #"kishore"];
NSMutableArray *dictArray = [[NSMutableArray alloc] init]; // created and initiated mutable array
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; // created and initiated mutable Dictionary
[dict setObject:#"object1" forKey:#"1"]; // added a key pair in dictionary (you can set multiple objects)
[dictArray addObject:dict]; // added dictionary to array (you can add multiple dictionary to array )
NSLog(#"dictionary inside an array : %#",dictArray[0][#"1"]); // access dictionary from array
You can try something like this
[NSArray arrayWithObjects:#{#"Image":#[#1,#2,#3]},#{#"Title":#[#1,#2,#3]},#{#"SubTitle":#[#1,#2,#3]}, nil];
You can easily create objects of array and access them back using following way.
NSArray *objimage=#[#"Test1.png",#"Test2.png",#"Test3.png"];
NSArray *objtitle=#[#"Test1",#"Test2",#"Test3"];
NSArray *objsubtitle=#[#"Test1",#"Test2",#"Test3"];
NSDictionary *obj_dictionary = #{#"image":objimage,#"Title":objtitle, #"subtitle":objsubtitle};
NSArray * obj_array= [[NSArray alloc] initWithObjects:obj_dictionary, nil]; // Create Array of nested objects
if([obj_array count] > 0) {
NSArray * imageArray = obj_array[0][#"image"]; // Access the nested objects in Array.
NSLog(#"%#", imageArray[0]);
}
first of all u need to declare correct variable name
NSArray *objImage=#[#"Test.png",#"Test.png",#"Test.png"];
NSArray *objTitle=#[#"Test",#"Test",#"Test"];
NSArray *objSubtitle=#[#"Test",#"Test",#"Test"];
at this point all u are created all the array, and u need to create dictionary like below
NSDictionary *obj_dictionary = #{#"image":objImage,#"title":objTitle, #"subtitle":objSubtitle};
// NSArray * obj_array = obj_dictionary[#"image"];
NSArray * obj_array = #[obj_dictionary]; //u can crate array of dictionary like this
in above obj_dictionary will contains all the array like below,
Title = (
Test,
Test,
Test
);
image = (
"Test.png",
"Test.png",
"Test.png"
);
subtitle = (
Test,
Test,
Test
);
and u can access the object in the dictionary like below using a key for example
NSArray * obj_array_images = obj_dictionary[#"image"];
gives an array of images that is associated with key image, similarly u can access other array like this by providing different keys associated with the dictionary obj_dictionary for example
NSArray * obj_array_titles = obj_dictionary[#"title"];
NSArray * obj_array_subtitles = obj_dictionary[#"subtitle"];
edit
NSArray *objImage=#[#"Test.png",#"Test.png",#"Test.png"];
NSArray *objTitle=#[#"Test",#"Test",#"Test"];
NSArray *objSubtitle=#[#"Test",#"Test",#"Test"];
NSDictionary *obj_dictionary = #{#"image":objImage,#"title":objTitle, #"subtitle":objSubtitle};
// NSArray * obj_array = obj_dictionary[#"image"];
NSArray * obj_array = #[obj_dictionary]; //u can crate array of dictionary like this

Resources