How to search element in array (Objective-C) - objective-c

I am new to Objective-C and I was looking for some help with my code. I want to search a word in a array.
#[#{
"name":"nick",
"Id":"2"
},
#{
"name":"Anna",
"Id":"4"
}]
I want to search name "nick" in array and fetch that complete object and create new array. I don't know how to do this in Objective-C.

NSArray * names = #[#{"name":"nick","Id":"2"},#{"name":"Anna","Id":"4"}];
NSMutableArray * results = [NSMutableArray arrayWithCapacity:1];
for ( NSDictionary * name in names )
{
if ( [name[#"name"] isEqualToString:#"nick"] )
{
[results addObject:name];
}
}
Something like that. Written from memory and not tested.

Related

Create array of dictionaries in objective c

I am fetching dictionaries from my local database.
My database array with name aryTitle_DB structure is as mentioned below.
( {
"date":13/9/2014;
"title"="abc"
}, { "date":13/9/2014;
"title"="def" }, { "date":13/9/2014;
"title"="ghi" }, {"date":14/9/2014;
"title"="abc" }, { "date":15/9/2014;
"title"="abc" }, { "date":15/9/2014;
"title"="def" })
I need following type of array structure from aryTitle_DB
( { "13/9/2014":("abc","def","ghi") }, { "14/9/2014":("abc") }, { "15/9/2014":("abc","def") } )
I did lot of search in stack overflow and in other tutorials but unable to find it.
please help to create such kind of array structure.
Help will be appreciable.
NSMutableArray *fromDB;
NSMutableArray *filtered;
filtered = [NSMutableArray new];
while (fromDB.count > 0){
NSDictionary *uniqueDate;
NSArray *filteredDate;
NSMutableArray *newDate;
uniqueDate = fromDB[0];
filteredDate = [fromDB filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self.date=%K",uniqueDate[#"date"]]];
[fromDB removeObjectsInArray:filteredDate];
newDate = [NSMutableArray new];
for (NSDictionary *oneDate in filteredDate) {
[newDate addObject:oneDate[#"title"]];
}
uniqueDate = #{uniqueDate[#"date"]:newDate};
[filtered addObject:uniqueDate];
};
this code should work. may be format of predicate should be changed, because i didn't test it. instead of format you can use formated string with filled var field.
In objective-C, there is no generics, this has only arrived with Swing in fact.
So your data structure is only a classical a NSArray of NSDictionary.
If you want to declare this ( { "13/9/2014":("abc","def","ghi") }, { "14/9/2014":("abc") }, { "15/9/2014":("abc","def") } ) in objC you ay do it like that
NSMutableArray* result = [NSMutableArray new];
NSDictionary * dict = [NSDictionary new];
// With Modern objective C syntax, it would be like that :
dict["13/9/2014"] = #{"abc","def","ghi"};
dict["14/9/2014"] = #{"abc"};
dict["15/9/2014"] = #{"abc","def"};
[result addObject:dict];
But of course you can create intermediate NSMutableArray for each values and use setValue:ForKey: method of NSDictionary to add it to dictionary.
Edit : added algorithm to parse DB answer
NSArray*DBAnswer; // this is your array containing the answer from the DB
NSDictionary*result=[NSDictionary new];
for(NSDictionary*d in DBAnswer)
{
NSMutableArray*list;
if(![result containsKey:d["date"]])
{
list = [NSMutableArray new];
result[d["date"]] = list;
}
else
{
list = result[d["date"]];
}
[list addObject:d["title"]];
}
// After that you have the structure in the result NSDictionary

How to remove elements of NSDictionary

I have NSArray of NSDictionaries I need to extract 2 values or remove the values I don't need from the dictionary in the example below I need to remove id and NumberValue. any of you knows how can I do that?
Array: (
{
customerUS= {
DisplayName = "level";
InternalName = "Number 2";
NumberValue = 1;
id = xwrf
},
customerCAN= {
DisplayName = "PurchaseAmount";
InternalName = "Number 1";
NumberValue = 3500;
id = adf;
};
}
)
I'll really appreciate your help.
First thing, You can not remove/insert/update value in (immutable) NSDictionary/NSArray you need to convert NSDictionary/NSArray to (mutable) NSMutableDictionary/NSMutableArray.
such like
NSArray *myArr = ....;
NSMutableArray *newMutableArr = [myArr mutableCopy];
Then you can change in newMutableArr.
Such like
for(int i = 0 ; i < newMutableArr.count ; i ++)
{
[[newMutableArr objectAtIndex:i] removeObjectForKey:#"id"];
[[newMutableArr objectAtIndex:i] removeObjectForKey:#"NumberValue"];
}
EDITED:
Without Use of for loop and removeObjectForKey, if you have array of dictionary and both are mutable then you can also delete a key and its object from all elements of the array like this:
[newMutableArr makeObjectsPerformSelector:#selector(removeObjectForKey:) withObject:#"id"];
[newMutableArr makeObjectsPerformSelector:#selector(removeObjectForKey:) withObject:#"NumberValue"];
I would advice you to read Apple documents.
For modifying any Collection object after it is created, you need the mutable version.
For NSDictionary we have NSMutableDictionary. Read here.
We have a method for removing objects:
- (void)removeObjectForKey:(id)aKey
There are other methods as well. You can easily refer them in the above mentioned documentation.
Find out removeObjectForKey for deleting record from NSMutabledictionary.
removeObjectForKey pass the key value whatever you have like
all this are your key
DisplayName,
InternalName,
NumberValue,
id
do like this
removeObjectForKey:#"id";
First of all you have to convert the array to mutable array and then you can remove the key-value pairs from dictionary.
NSMutableArray *mutableArray = [yourArray mutableCopy];for(int i=0;i<mutableArray.count;i++){ NSMutableDictionary *outerDictionary = [mutableArray objectAtIndex:i]; for(NSString *key in outerDictionary.allKeys){ NSMutableDictionary *innerDictionary = [outerDictionary objectForKey:key]; [innerDictionary removeObjectForKey:#"id"]; [innerDictionary removeObjectForKey:#"NumberValue"]; }
}

What is the best way to build a one-to-many relationship?

I have an array of Videos objects with, among other things, the properties id and tags.
I want to build a dictionary whose key is a tag and whose value is an array of id's.
For example, some Video objects might look like this:
Video{ id:1, tags:[funny,political,humor] }
Video{ id:2, tags:[political,america] }
I want the result dictionary to look like this:
VideosWithTags["funny":[1]; "political":[1,2]; "humor":[1]; "america":[2]]
Is there a standard algorithm to accomplish this?
Currently I'm doing something like this:
for (NSDictionary *video in videos)
{
NSNumber *videoId = [video objectForKey:#"id"];
NSArray *tags = [video objectForKey:#"tags"];
for (NSString *tag in tags)
{
NSMutableArray *videoIdsForTag = nil;
if ([videosAndTags objectForKey:tag] != nil) //same tag with videoIds already exists
{
videoIdsForTag = [videosAndTags objectForKey:tag];
[videoIdsForTag addObject:videoId];
//add the updated array to the tag key
[videosAndTags setValue:videoIdsForTag forKey:tag];
}
else //tag doesn't exist yet, create it and add the videoId to a new array
{
NSMutableArray *videoIds = [NSMutableArray array];
[videoIds addObject:videoId];
//add the new array to the tag key
[videosAndTags setObject:videoIds forKey:tag];
}
}
}
You can make this look a little cleaner by using the new literal syntax.
I think you could benefit by making your if branches do less work. e.g. You would be better of trying to retrieve the videoIds array then if it doesn't exist - create it and add it to the videosAndTags object and then the code after this point can be consistent with no duplication of logic
for (NSDictionary *video in videos) {
NSNumber *videoId = video[#"id"];
NSArray *tags = video[#"tags"];
for (NSString *tag in tags) {
NSMutableArray *videoIds = videosAndTags[tag];
if (!videoIds) {
videoIds = [NSMutableArray array];
videosAndTags[tag] = videoIds;
}
// This is the only line where I manipulate the array
[videoIds addObject:videoId];
}
}
NSArray* videos =
#[#{ #"id" : #1, #"tags" : #[ #"funny", #"political", #"humor" ] },
#{ #"id" : #2, #"tags" : #[ #"political", #"america" ] } ];
NSMutableDictionary* videosAndTags = [NSMutableDictionary new];
// find distinct union of tags
NSArray* tags = [videos valueForKeyPath: #"#distinctUnionOfArrays.tags"];
// for each unique tag
for( NSString* tag in tags )
{
// filter array so we only have ones that have the right tag
NSPredicate* p = [NSPredicate predicateWithFormat: #"tags contains %#", tag];
videosAndTags[ tag ] = [[videos filteredArrayUsingPredicate: p] valueForKeyPath: #"id"];
}
Here is another approach using NSPredicate and valueForKeyPath.
I don't used them often, but sometimes they can prove to be useful.
(I think they call this the Functional Programming style of things, but I am not so sure)
NSPredicate reference
Key Value Coding

Extracting data from multidimensional NSMutableArray into a simpler array

I'm learning iOS but have an issue extracting data from a multidimensional NSMutableArray, I've looked at various solutions but have not yet found one..
I have an NSMutableArray like
{
"service_0" = {
"name" = "name1";
"description" = "description1";
};
"service_2" = {
"name" = "name2";
"description" = "description2";
};
Etc...
}
I wish to extract data into a new NSMutableArray (or NSArray) to get the following output for use in text labels such as = [myArray objectAtIndex:indexPath.row]
(
name1,
name2,
Etc...
)
What would be the best solution? Thanks
Assuming that is an array of dictionaries, unlike in the question...
NSArray *newArray = [oldArray valueForKeypath:#"name"];
You can make it mutable using mutableCopy, if you wish.

How do I traverse a multi dimensional NSArray?

I have array made from JSON response.
NSLog(#"%#", arrayFromString) gives the following:
{
meta = {
code = 200;
};
response = {
groups = (
{
items = (
{
categories = (
{
icon =
"http://foursquare.com/img/categories/parks_outdoors/default.png";
id = 4bf58dd8d48988d163941735;
and so on...
This code
NSArray *arr = [NSArray arrayWithObject:[arrayFromString valueForKeyPath:#"response.groups.items"]];
gives array with just one element that I cannot iterate through. But if I write it out using NSLog I can see all elements of it.
At the end I would like to have an array of items that I can iterate through to build a datasource for table view for my iPhone app.
How would I accomplish this?
EDIT:
I have resolved my issue by getting values from the nested array (objectAtIndex:0):
for(NSDictionary *ar in [[arrayFromString valueForKeyPath:#"response.groups.items"] objectAtIndex:0]) {
NSLog(#"Array: %#", [ar objectForKey:#"name"]);
}
First, the data structure you get back from the JSON parser is not an array but a dictionary: { key = value; ... } (curly braces).
Second, if you want to access a nested structure like the items, you need to use NSObject's valueForKeyPath: method. This will return an array of all items in your data structure:
NSLog(#"items: %#", [arrayFromString valueForKeyPath:#"response.groups.items"]);
Note that you will loose the notion of groups when retrieving the item objects like this.
Looking at the JSON string you posted, response.groups.items looks to be an array containing one item, a map/dictionary containing one key, "categories." Logging it out to a string is going to traverse the whole tree, but to access it programmatically, you have to walk the tree yourself. Without seeing a more complete example of the JSON, it's hard to say exactly what the right thing to do is here.
EDIT:
Traversing an object graph like this is not that simple; there are multiple different approaches (depth-first, breadth-first, etc,) so it's not necessarily something for which there's going to be a simple API for you to use. I'm not sure if this is the same JSON library that you're using, but, for instance, this is the code from a JSON library that does the work of generating the string that you're seeing. As you can see, it's a bit involved -- certainly not a one-liner or anything.
You could try this, which I present without testing or warranty:
void __Traverse(id object, NSUInteger depth)
{
NSMutableString* indent = [NSMutableString string];
for (NSUInteger i = 0; i < depth; i++) [indent appendString: #"\t"];
id nextObject = nil;
if ([object isKindOfClass: [NSDictionary class]])
{
NSLog(#"%#Dictionary {", indent);
NSEnumerator* keys = [(NSDictionary*)object keyEnumerator];
while (nextObject = [keys nextObject])
{
NSLog(#"%#\tKey: %# Value: ", indent, nextObject);
__Traverse([(NSDictionary*)object objectForKey: nextObject], depth+1);
}
NSLog(#"%#}", indent);
}
else if ([object isKindOfClass: [NSArray class]])
{
NSEnumerator* objects = [(NSArray*)object objectEnumerator];
NSLog(#"%#Array (", indent);
while (nextObject = [objects nextObject])
{
__Traverse(nextObject, depth+1);
}
NSLog(#"%#)", indent);
}
else
{
NSLog(#"%#%#",indent, object);
}
}
void Traverse(id object)
{
__Traverse(object, 0);
}