Multi dimensional array containing array of dictionaries - ios

Trough my ios first app developpement i have to re-order an array containing dictionaires, parsed from a xml document, the purpose of re-ordering it is to send it to a function that build a collapsible, so it need a childCell index and a parentCell Index to print the strings of each child then pass to another parent. The problem is here : i'am able to fill my big array containing arrays of dictionaries, then i that array and do a loop to fill the childArray to contain multiple dictionaries, then i add this child array to my parent array, every thing seem to run but it gives me an empty array at the end. i put my code to show you how i tried to do this :
stories is the NSArray of dictionaries, childArray is the Array that should contain the dictionaries of stories, and parentArray is the Array that contains it all.
If someone who already did that can explain me were it goes wrong please it would be very much appreciated.
-(NSMutableArray *)orderChildsAndParents:(NSMutableArray *)fromArray
{
int varial = 0;
int catIndex = 0;
NSMutableArray *parentArray = [NSMutableArray array];
while(varial < [stories count])
{
NSString* cleanedString = [[[[stories objectAtIndex:varial] objectForKey:#"category"] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
componentsJoinedByString:#""];
if ([cleanedString isEqualToString:[category objectAtIndex:catIndex] ])
{
if (!childArray || !childArray.count)
childArray = [NSMutableArray array];
[childArray addObject:[stories objectAtIndex:varial]];
varial++;
}
else{
[parentArray addObject:childArray];
[childArray removeAllObjects];
catIndex++;
}
}
NSLog(#"%#", parentArray);
return parentArray;
}
- (NSString *) labelForCellAtChildIndex:(NSInteger) childIndex withinParentCellIndex:(NSInteger) parentIndex {
NSMutableArray *orderedArray = [self orderChildsAndParents:stories];
NSLog(#"format string %#", [[[orderedArray objectAtIndex:parentIndex] objectAtIndex:childIndex] objectForKey:#"name"]); // empty :8
return [[[orderedArray objectAtIndex:parentIndex] objectAtIndex:childIndex] objectForKey:#"name"];
}

Related

Looping thru NSArray of NSString logic

I need help with the following:
I have an NSArray with NSStrings, I want to loop thru these strings and find a matching string, when match is found the strings after this match will be extracted into an NSDictionary until a certain other match is hit.
Here is an example:
NSArray *array = #[#"Fruit",#"Apple",#"Vegtable",#"Tomato",#"Fruit",#"Banana",#"Vegtable",#"Cucumber"];
So I want to loop thru this array and split it in 2 arrays one for fruit and one for vegetable.
Anyone can help with the logic?
Thanks
This is probably the simplest way to solve the problem:
NSArray *array = #[#"Chair",#"Fruit",#"Apple",#"Orange",#"Vegetable",#"Tomato",#"Fruit",#"Banana",#"Vegetable",#"Cucumber"];
NSMutableArray *fruitArray = [NSMutableArray array];
NSMutableArray *vegetableArray = [NSMutableArray array];
NSMutableArray *currentTarget = nil;
for (NSString *item in array)
{
if ([item isEqualToString: #"Fruit"])
{
currentTarget = fruitArray;
}
else if ([item isEqualToString: #"Vegetable"])
{
currentTarget = vegetableArray;
}
else
{
[currentTarget addObject: item];
}
}
In one iteration over the array, you just keep adding items to a result array using a pointer to one of two result arrays according to the last occurrence of the #"Fruit" or #"Vegetable" string.
This algorithm ignores all items before the first occurrence of the #"Fruit" or #"Vegetable" string, because the currentTarget is initialized to nil, which ignores the addObject: messages. If you want different behaviour, just change the initialization.
You said you wanted the results in a NSDictionary, but didn't specify what should be the key. If you want one NSDictionary with two keys, Fruit and Vegetable, and values NSArrays containing the items, just use the arrays previously created:
NSDictionary *dict = #{ #"Fruit": fruitArray, #"Vegetable": vegetableArray };
PS: You have a typo in your example, Vegtable instead of Vegetable. I corrected it in my code, so keep it in mind.
If I completely understand you:
NSArray *array = #[#"Fruit",#"Apple",#"Vegtable",#"Tomato",#"Fruit",#"Banana",#"Vegtable",#"Cucumber"];
NSMutableArray *fruits = [NSMutableArray array];
NSMutableArray *vegtables = [NSMutableArray array];
for (NSInteger i = 0; i < array.count; ++i){
if ([array[i] isEqualToString:#"Fruit"]){
++i;
[fruits addObject:array[i]];
}
else if ([array[i] isEqualToString:#"Vegtable"]){
++i;
[vegtables addObject:array[i]];
}
}

iOS NSDictionary Values

I have an array of NSDictionaries and i can access the values in them just fine but i am trying to filter these dictionaries down based on a user's search (user can only search by the dictionary key (#"uniqueSignName").
Once the user has searched through the names property i then need to display ALL dictionary associated data for that #"uniqueSignName" value.
I do the following code and always get the correct amount of NSLogs. For the life of me i cannot remember how to GET those dictionaries.
for (int i = 0; i < [filteredDictionaries count]; i++) {
if ([[[filteredDictionaries valueForKey:#"uniqueSignName"] objectAtIndex:i] isEqualToString:[self.filteredResults objectAtIndex:indexPath.row]]) {
NSLog(#"Power Rangers");
}
}
Eg: I search for "John"
NSLog: #"Power Rangers"
Correctly only appears once.
Now, how do i access another property of "John's" dictionary?
If you want to search the name then better way is that to use NPredicate without iterating the array.
Please see the below example..it may help you...
// Here array is your main array...
NSArray *filteredarray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(uniqueSignName == %#)", #"John"]];
So the problem is solved, I can now access all the filtered properties.
for (NSDictionary *dict in filteredDictionaries) {
if ([[self.filteredResults objectAtIndex:indexPath.row] isEqualToString: dict[#"uniqueSignName"]]) {
NSString *myString = [NSString stringWithFormat:#"%#", dict[#"pType"]];
NSLog(#"hugh: %#", myString);
myString = displayPtype;
}
}

Multiple dictionaries within an array and Checking for duplicate keys - Objective C

I have an array which contains multiple Dictionaries each one with 3 keys (#"date", #"username", #"text").
What I want to check for, is whether the same user (#"username") exists in more than one dictionary in that Array. And, if she does, combine the text for those "duplicates" into one dictionary.
I have considered this answer to check for duplicates and this one
but I cannot figure out how to combine these two.
Jumping in here because although I think you should work on the code yourself first, I think Miro's answer is more complicated than the issue requires and though I like the idea of using predicates in Greg's answer, here's a 3rd solution that (1) wouldn't require you to change your data structure and (2) references the necessary loops...
The way I'd do it: Create an NSMutableArray then start adding the usernames in order. If the NSMutableArray already contains the username though, don't add another instance of the username, but instead merge the dictionary info.
ex.
// Note: I'm calling your array of user dictionaries userArray.
// Create a username array to store the usernames and check for duplicates
NSMutableArray *usernames = [[NSMutableArray alloc] init];
// Create a new userArray to store the updated dictionary info, merged
// entries et. al.
NSMutableArray *newUserArray = [[NSMutableArray alloc] init];
// Go through the array of user dictionaries
for (NSDictionary *userDict in userArray) {
// If the usernames array doesn't already contain the username,
// add it to both the usernames array and the newUserArray as is
if (![usernames containsObject:[userDict objectForKey:#"username"]]) {
[usernames addObject:[userDict objectForKey:#"username"]];
[newUserArray addObject:userDict];
}
// Otherwise, merge the userArray entries
else {
// Get a mutable copy of the dictionary entry at the first instance
// with this username
int indexOfFirstInstance = [usernames indexOfObject:[userDict objectForKey:#"username"]];
NSMutableDictionary *entry = [[newUserArray objectAtIndex:indexOfFirstInstance] mutableCopy];
// Then combine the "text" or whatever other values you wanted to combine
// by replacing the "text" value with the combined text.
// (I've done so with a comma, but you could also store the value in an array)
[entry setValue:[[entry objectForKey:#"text"] stringByAppendingString:[NSString stringWithFormat:#", %#", [userDict objectForKey:#"text"]]] forKey:#"text"];
// Then replace this newly merged dictionary with the one at the
// first instance
[newUserArray replaceObjectAtIndex:indexOfFirstInstance withObject:entry];
}
}
Maybe something like this [untested] example? Loop through, maintain a hash of existing items, and if a duplicate is found then combine with existing and remove.
NSMutableArray main; // this should exist, with content
NSMutableDictionary *hash = [[NSMutableDictionary alloc] init];
// loop through, backwards, as we're attempting to modify array in place (risky)
for(int i = [main count] - 1; i >= 0; i--){
// check for existing
if(hash[main[i][#"username"]] != nil){
int existingIdx = [hash[main[i][#"username"]] integerValue]; // get existing location
main[existingIdx][#"text"] = [main[existingIdx][#"text"] stringByAppendingString:main[i][#"text"]]; // "combine text" .. or however you'd like to
[main removeObjectAtIndex:i]; // remove duplicate
} else {
[hash setValue:[[NSNumber alloc] initWithInt:i] forKey:main[i][#"username"]]; // mark existance, with location
}
}
If you use NSMutableDictionary, NSMutableArray and NSMutableString you can do it with predicate like that:
NSMutableDictionary *d1 = [#{#"username": #"Greg", #"text" : [#"text 1" mutableCopy]} mutableCopy];
NSMutableDictionary *d2 = [#{#"username": #"Greg", #"text" : [#"text 2" mutableCopy]} mutableCopy];
NSMutableDictionary *d3 = [#{#"username": #"John", #"text" : [#"text 3" mutableCopy]} mutableCopy];
NSMutableArray *array = [#[d1, d2, d3] mutableCopy];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username = %#", #"Greg"];
NSArray *filterArray = [array filteredArrayUsingPredicate:predicate];
NSMutableDictionary * firstDict = filterArray[0];
for (NSDictionary *d in filterArray)
{
if (firstDict != d)
{
[firstDict[#"text"] appendString:d[#"text"]];
[array removeObject:d];
}
}

How to see if object is contained in an embedded NSArray, then grab the other items in the set

I currently have a NSArray which contains many NSArrays, each containing a pair of NSStrings such like the following: [["A", "B"], ["U", "A"], ["X", "Y"], ...], and I am interested first checking to see if it contains a particular object, and then grabbing the other paired object and putting it in an array. For example, if I am checking for "A" in the above array, the result array would contain ["B", "U"]
I know how to iterate over each array, but am trouble deciding how to grab the paired object inside the array... thanks!
for (NSArray *innerArray in outerArray){
if ([innerArray containsObject: #"A"]){
//how to extract the other object and save it to an array?
}
}
NSMutableArray *results = [NSMutableArray array];
for (NSArray *innerArray in outerArray){
// Get the index of the object we're looking for
NSUInteger index = [innerArray indexOfObject:#"A"];
if (index != NSNotFound) {
// Get the other index
NSUInteger otherIndex = index == 0 ? 1 : 0;
// Get the other object and add it to the array
NSString *otherString = [innerArray objectAtIndex:otherIndex];
[results addObject:otherString];
}
}
Should do the trick.
If you're sure that your data will have exactly the structure you describe, you can use the fact that inner array have exactly 2 element - so index of "other" element will be 1-indexOfYourElement:
for (NSArray *innerArray in outerArray){
NSUInteger ix = [innerArray indexOfObject:#"A"];
if (ix!=NSNotFound){
id objectToAdd = innerArray[1-ix];
// Do something with it
}
}
Here's one possible way:
NSMutableArray* results = [[NSMutableArray alloc] init];
for (NSArray *innerArray in outerArray){
if ([innerArray containsObject: #"A"]){
[results addObjectsFromArray: [innerArray enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL *stop) {
if (![obj isEqual: #"A"])
{
[results addObject: obj];
}
}]];
}
}

Dynamica string count in NSMutableArray in NSMutableDictionary

I am familiar with getting a string count from a known array
int numberOfWords = [self.wordArray count];
but I have an unknown number of strings in an unknown number of arrays, all referenced by a dictionary. This works - good.
NSMutableDictionary *eqClasses = [[NSMutableDictionary alloc] init];
The arrays and strings are added at runtime (with help of this board):
NSMutableArray* array = [eqClasses objectForKey:wordPattern];
if(!array) {
// create new array and add to dictionary if wordPattern not found
array = [NSMutableArray array];
[eqClasses setObject:array forKey:wordPattern];
}
[array addObject:tempWordStr];
Now I need to iterate through the dictionary and get the array with the largest word count. Is there a way to scroll through all the arrays in the dictionary without using a key (I won't know all the word patterns as they are generated dynamically), AND once I find the array with the most words, get that array/value and key/wordpattern?
Well, there is a way to get all the keys within a dictionary:
NSArray *keyArray = [myDict allKeys];
And then you just go through the array and get the object for each key.
A fast enumeration should work nicely.
for (NSString *string in NSArray){
...
} //Assuming your keys are strings!
You can save each string to a temporary string, and when encountering a new string, compare to find the longer one. If it's longer, replace the old string with the longer one.
Hope this helped! ^_^
^_^
Okay, so now that you have an array full of all the keys in the dictionary,
you can iterate through the entire array and get the corresponding value (the string) for each key.
NSArray *keyArray = [myDict allKeys]; //This gets all the keys
NSString *tempString = #""; //This is the string you will save the longest string in. It gets updated when a longer string is found in the following loop.
for (NSString *string in keyArray){
NSString *stringFromCurrentKey = [myDict objectForKey:string];
if(stringFromCurrentKey.length > tempString.length){
tempString = stringFromCurrentKey;
}
} //By the end, you should be left with the longest string contained in tempString!
^_^ Hope this made sense and helped!
Try this code:
NSArray *largestArray = nil;
for (NSString *key in dictionary)
{
NSArray *array = [dictionary objectForKey:key];
if (array.count > largestArray.count) // largestArray.count is 0 if largestArray is nil
{
largestArray = array;
}
}

Resources