parsing NSMutableDictionary with required format - objective-c

I have an objective C object 'Obj' with an
#property (strong, nonatomic) NSMutableDictionary *obj;
This gets populated with data from an api in following format.
{
0 = ( 0, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
1 = ( 1, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
2 = ( 2, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
3 = ( 3, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
4 = ( 4, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
5 = ( 5, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
6 = ( 6, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
}
I need to parse the data and send it back as an array in following format.
`{
[ 0, 7, 00, 8, 59 ],
[0, 15, 00, 16, 59] ,
[0, 19, 00, 20, 59] ,
[ 1, 7, 00, 8, 59 ],
[1, 15, 00, 16, 59] ,
[1, 19, 00, 20, 59],
……
……
[ 6, 7, 00, 8, 59 ],
[6, 15, 00, 16, 59] ,
[6, 19, 00, 20, 59]
}`
Where 0,1,2,3,4,5,6 are days and rest of the information is hours and mins. so for each slot, the format is
`[day, from_hour, from_min, to_hour, to_min],
[0, 7, 0, 8, 59],`
A day could have multiple slots or just one slot.
So far I manage to run a loop and separate each day's record as below.
NSMutableArray *elementArray =[[NSMutableArray alloc ]init];
NSMutableArray *results =[[NSMutableArray alloc ]init];
NSInteger starthour = 0 ;
NSInteger startmin = 0 ;
NSInteger endhour = 0 ;
NSInteger endmin = 0 ;
NSMutableArray *temp = [[NSMutableArray alloc]init];
NSString *string;
int i = 0;
for ( i = 0; i <=6; i ++){
string = [NSString stringWithFormat:#"%d",i];
elementArray =[Obj.obj valueForKey:string];
starthour = [[elementArray objectAtIndex:1]integerValue];
startmin =([[elementArray objectAtIndex:1]floatValue]-[[elementArray objectAtIndex:1]integerValue])*100;
endhour = [[elementArray objectAtIndex:2]integerValue];
endmin =([[elementArray objectAtIndex:2]floatValue]-[[elementArray objectAtIndex:2]integerValue])*100;
NSNumber *day = [NSNumber numberWithInteger:[string integerValue]];
NSNumber *starthour1 = [NSNumber numberWithInteger:(int)starthour];
NSNumber *startmin1 = [NSNumber numberWithInteger:(int)startmin];
NSNumber *endhour1 = [NSNumber numberWithInteger:(int)endhour];
NSNumber *endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:temp];
}
This gives me access to each record. My thought process is saying I could solve this by going through each record and populating the required array as, 'i' being the day, then running a nest loop on each record and extracting hours and mins?

You don't say what your problem actually is, i.e. you started on a solution and stopped and turned to SO, why?
Let's see if we can help you along with some pseudo-code.
You have a dictionary of arrays. the keys represent day numbers as do the first element of each array. After the first array element the elements come in pairs, each is a string containing a textual representation of hours and minutes separated by a full stop. You want and array of arrays where each element has 5 members: day number, start hour, start min, end hour, end minute, all as numbers.
A basic algorithm to handle this is two nested loops. You need somewhere to store the result:
results <- new empty array
Now you need to iterate over your dictionary:
for every key in sourceDictionary
elementArray = sourceDictionary[key]
[This is the loop you've written, except you generated the keys and looked them up while here we extract the keys from the dictionary. If you wish to process the keys in a particular order then generating them in that order, or extracting and sorting them, will handle that.]
Now you'd better do some data validation, elementArray should have at least the day number and one pair of strings in it, test for that:
check elementArray count > 1 and odd else handle error
Now you need to process each pair of strings, first access them:
cursor <- 1 // element 0 is the repeated day number
while cursor < elementArray count do
startTime <- elementArray[cursor]
endTime <- elementArray[cursor+1]
cursor <- cursor + 2 // ready for next iteration
So now you have the day number, key, and the start and end times as string, startTime & endTime. Now you need to split your time strings at the full stop, returning an array of substrings:
startParts <- startTime split at "."
More checks, did you get two parts?
check startParts count is 2 else handle error
Now convert each substring to an integer:
startHours <- parse startParts[0] as integer
startMins <- parse startParts[1] as integer
And keep checking:
check startHours in [0, 23] and startMins in [0, 59] else handle error
You've now got the five values you want, add them to your results array:
results <- results append array of (key, startHours, startMins, endHours, endMins)
Now just convert that to Objective-C and fill in the details. The first loop could be a for in one, the second a for(init; test; increment) one. For splitting a string look at NSString's methods, one will fit the bill. For parsing there are multiple options including NSString methods.
HTH

I got it working with desired output, but code looks messy, could be made elegant.
` NSMutableArray *elementArray =[[NSMutableArray alloc ]init];
NSMutableArray *results =[[NSMutableArray alloc ]init];
NSInteger starthour = 0 ;
NSInteger startmin = 0 ;
NSInteger endhour = 0 ;
NSInteger endmin = 0 ;
NSNumber *starthour1 ;
NSNumber *startmin1 ;
NSNumber *endhour1 ;
NSNumber *endmin1 ;
NSMutableArray *temp = [[NSMutableArray alloc]init];
NSString *string;
int i = 0;
for ( i = 0; i <=6; i ++){
string = [NSString stringWithFormat:#"%d",i];
elementArray =[Obj.obj valueForKey:string];
starthour = [[elementArray objectAtIndex:1]integerValue];
startmin =([[elementArray objectAtIndex:1]floatValue]-[[elementArray objectAtIndex:1]integerValue])*100;
endhour = [[elementArray objectAtIndex:2]integerValue];
endmin =([[elementArray objectAtIndex:2]floatValue]-[[elementArray objectAtIndex:2]integerValue])*100;
NSNumber *day = [NSNumber numberWithInteger:[string integerValue]];
starthour1 = [NSNumber numberWithInteger:(int)starthour];
startmin1 = [NSNumber numberWithInteger:(int)startmin];
endhour1 = [NSNumber numberWithInteger:(int)endhour];
endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:[temp copy]];
[temp removeAllObjects];
starthour = [[elementArray objectAtIndex:3]integerValue];
startmin =([[elementArray objectAtIndex:3]floatValue]-[[elementArray objectAtIndex:3]integerValue])*100;
endhour = [[elementArray objectAtIndex:4]integerValue];
endmin =([[elementArray objectAtIndex:4]floatValue]-[[elementArray objectAtIndex:4]integerValue])*100;
starthour1 = [NSNumber numberWithInteger:(int)starthour];
startmin1 = [NSNumber numberWithInteger:(int)startmin];
endhour1 = [NSNumber numberWithInteger:(int)endhour];
endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:[temp copy]];
[temp removeAllObjects];
starthour = [[elementArray objectAtIndex:5]integerValue];
startmin =([[elementArray objectAtIndex:5]floatValue]-[[elementArray objectAtIndex:5]integerValue])*100;
endhour = [[elementArray objectAtIndex:6]integerValue];
endmin =([[elementArray objectAtIndex:6]floatValue]-[[elementArray objectAtIndex:6]integerValue])*100;
starthour1 = [NSNumber numberWithInteger:(int)starthour];
startmin1 = [NSNumber numberWithInteger:(int)startmin];
endhour1 = [NSNumber numberWithInteger:(int)endhour];
endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:[temp copy]];
[temp removeAllObjects];
`
The output is what I wanted looks like below.
(
(
0,
7,
0,
8,
59
),
(
0,
15,
0,
16,
59
),
(
0,
19,
0,
20,
59
),
(
1,
7,
0,
8,
59
),
(
1,
15,
0,
16,
59
),
(
1,
22,
0,
23,
59
),
(
2,
7,
0,
8,
59
),
(
2,
15,
0,
16,
59
),
(
2,
19,
0,
20,
59
),
(
3,
7,
0,
8,
59
),
(
3,
15,
0,
16,
59
),
(
3,
22,
0,
23,
59
),
(
4,
7,
0,
8,
59
),
(
4,
15,
0,
16,
59
),
(
4,
19,
0,
20,
59
),
(
5,
7,
0,
8,
59
),
(
5,
15,
0,
16,
59
),
(
5,
22,
0,
23,
59
),
(
6,
7,
0,
8,
59
),
(
6,
15,
0,
16,
59
),
(
6,
19,
0,
20,
59
)
)

Related

Sort NSMutableDictionary in ASC order

In my Xcode Project (Objective-C), i store json Result in a NSMutableDictionary, but the result is in false order direction.
How can i sort a NSMutableDictionary is ASC order on Objective-C.
Here is my NSMutableDictionary:
{
3 = (
11,
12,
13,
14,
15,
16,
17,
18,
19,
20
);
2 = (
2,
3,
4,
5,
6,
7,
8,
9,
10
);
1 = (
0,
1
);
4 = (
21,
22,
23,
24,
25,
26
);
}
I expect a sort order 1,2,3,4 for UITableView Section.
#rmaddy is right,the following is the implementation code, very simple.
- (NSMutableArray *)sortDictionary:(NSMutableDictionary *)dictionary {
NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSMutableArray *sortedArray = [NSMutableArray arrayWithCapacity:sortedKeys.count];
for (NSString *key in sortedKeys) {
[sortedArray addObject:[dictionary objectForKey:key]];
}
return sortedArray;
}
example
NSDictionary *dict = #{#"3":#{#"3333":#"3333"},
#"2":#{#"2222":#"2222"},
#"1":#{#"1111":#"1111"},
#"4":#{#"4444":#"444"}};
[self sortDictionary:dict];
result:
sortedArray :(
{
1111 = 1111;
},
{
2222 = 2222;
},
{
3333 = 3333;
},
{
4444 = 444;
}
)

Working with NSDictionary to array

I have 2 NSArray with contents ids and the other contents are urls
But when I create NSDictionary its look like this (from NSLog):
2015-07-03 17:10:51.072 hibridTesting[4950:166675] {
(
) = (
);
(
30,
31
) = (
"https://www.google.com",
"https://www.yahoo.com"
);
(
10,
11,
12,
13
) = (
"https://www.facebook.com/",
"https://www.sapo.pt",
"https://www.sapo.pt",
"https://www.sapo.pt"
);
(
20,
21,
22,
23,
24,
25
) = (
"https://www.google.com",
"https://www.google.com",
"https://www.google.com",
"https://www.google.com",
"https://www.google.com",
"https://www.google.com"
);
}
and if I do this
arrayDeSitesSubmenus = [mydictionary objectForKey:#"21"];
and if I print my arrayDeSitesSubmenus it says nil.
What I want is each id for url, and what I understand is group of keys to a group of urls
EDIT:
my logs from arrays is:
2015-07-03 17:33:55.771 hibridTesting[5122:174427] (
(
"https://www.facebook.com/",
"https://www.sapo.pt",
"https://www.sapo.pt",
"https://www.sapo.pt"
),
(
"https://www.google.com",
"https://www.google.com",
"https://www.google.com",
"https://www.google.com",
"https://www.google.com",
"https://www.google.com"
),
(
"https://www.google.com",
"https://www.yahoo.com"
),
(
),
(
),
(
),
(
)
)
2015-07-03 17:33:55.771 hibridTesting[5122:174427] (
(
10,
11,
12,
13
),
(
20,
21,
22,
23,
24,
25
),
(
30,
31
),
(
),
(
),
(
),
(
)
)
i take my arrays from xmlparse , thats why my logs looks like that
thanks.
How are you creating your NSDictionary?
When creating NSDictionary you have two option:
first:
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:#"value1", #"key1", nil];
the other is
NSDictionary *mdictionary = #{ #"key1" : #"value1" };
Since you already have the array for both keys and values, the best one for you is using initWithObjects:forKeys which accepts array of values and keys and arrange accordingly.
NSArray *keys = #[#"1", #"2", #"3", #"4", #"5"];
NSArray *values = #[#"value1", #"value2", #"value3", #"value4", #"value5"];
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:values forKeys:keys];
and the output will be:
{
1 = value1;
2 = value2;
3 = value3;
4 = value4;
5 = value5;
}
but if your key are numbers like
NSArray *keys = #[#1, #2, #3, #4, #5];
NSArray *values = #[#"value1", #"value2", #"value3", #"value4", #"value5"];
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:values forKeys:keys];
//This is wrong and will return (null)
//
//NSLog(#"%#", [dictionary objectForKey:#"1"]);
The correct one is:
NSLog(#"%#", [dictionary objectForKey:#1]);
or
NSLog(#"%#", [dictionary objectForKey:[NSNumber numberWithInt:1]]);
Hope this is helpful to you. Cheers!

Sorting NSMuatbleArray with NSInterger values

I want to sort NSMutableArray which have NSInteger values inside. I tried to use this solution:
NSArray *sorted = [array sortedArrayUsingSelector:#selector(compare:)];
It almost worked, so i want to ask why not everything alright with it. Here is example of data:
not sorted = (
30,
42,
54,
6,
18
)
sorted = (
18,
30,
42,
54,
6
)
We can see that it sorted everything but 6 value which is at the end off array.
Why this could happened ?
Thank you.
Full method:
- (void) initialize{
NSInteger min = 30;
NSInteger interval = 12;
NSInteger count = floor(60/interval);
for (int i = 0; i < count; i++) {
[array addObject:[NSString stringWithFormat:#"%i",min]];
min +=interval;
if (min > 60)
min -= 60;
}
//DLog(#"not sorted = %#",minutes);
array = [[array sortedArrayUsingSelector:#selector(compare:)] mutableCopy];
//DLog(#"sorted = %#",minutes);
}
You are getting problem in above case because you are sorting string values not a NSNUMBER.
You have to use NSNumber to add objects of integer. Then do something like:
NSMutableArray *array = [[NSMutableArray alloc ] initWithObjects:
[NSNumber numberWithInt:10],
[NSNumber numberWithInt:50],
[NSNumber numberWithInt:5],
[NSNumber numberWithInt:3],
nil];
NSLog(#"SORTED = %#",[array sortedArrayUsingSelector:#selector(compare:
)]);
This will give you a sorted array.

Migrating, and add data, on file using NSDictionary code issues

I am migrating from an old version (v2) to the new version (v3) of my app and by that adding two new fields for each player into the playerdata.plist. The reason why i am putting '99' in the new fields is only for testing as i am testing on a v3 file, with the extra fields, to make it easier.
What i am trying to accomplish is:
a. read the file with the player data
b. add to new fields
c. store the file
The current result is that i am storing the same data for each players after the migration.
Code:
- (void)migratePlayerDataPlist {
//====THIS PIECE OF CODE SHOULD BE REMOVED AFTER CERTAIN TIME AS IT WILL NOT BE NEEDED====//
//====..WHEN ALL OLD USERS HAVE MIGRATED. THIS IS WRITTEN SEPTEMBER 5 2012 VERSION 3.0====//
// This procedure migrates the old playerdatafile to version 3 of the game
//Prepare File Manager
NSString *filePath = [self dataFilePath];
NSFileManager *fileMgr;
fileMgr = [NSFileManager defaultManager];
if ([fileMgr fileExistsAtPath: filePath] == YES) {
dataArray = [[NSMutableArray alloc]init];
NSMutableDictionary *gameFileDict = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
NSLog(#"gameFileDict: %#", gameFileDict);
myKeyArray = [gameFileDict allKeys];
int nrOfKeys = [myKeyArray count];
NSMutableDictionary *migrationDict = [[NSMutableDictionary alloc]initWithCapacity:200];
NSMutableDictionary *xmigrationDict = [[NSMutableDictionary alloc]initWithCapacity:200];
NSLog(#"nrOfKeys: %i", nrOfKeys);
for (int oo = 0; oo < nrOfKeys; oo++) {
[dataArray removeAllObjects]; // Clean array
theObjects = [gameFileDict valueForKey:[myKeyArray objectAtIndex:oo]];
[dataArray addObject:[theObjects objectAtIndex:0]]; // diffSelection
[dataArray addObject:[theObjects objectAtIndex:1]]; // # of games played
[dataArray addObject:[theObjects objectAtIndex:2]]; // # correct answers
[dataArray addObject:[theObjects objectAtIndex:3]]; // # questions
[dataArray addObject:[NSNumber numberWithInt:99]]; // >>New field<< # of games won
[dataArray addObject:[NSNumber numberWithInt:99]]; // >>New field<< # of games lost
xmigrationDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:dataArray, [myKeyArray objectAtIndex:oo], nil];
[migrationDict addEntriesFromDictionary:xmigrationDict];
}
NSLog(#"xmigrationDict: %#", xmigrationDict);
NSLog(#"migrationDict: %#", migrationDict);
NSLog(#"theObjects: %#", theObjects);
// Delete the old file
[fileMgr removeItemAtPath:filePath error:NULL];
// Resave the file with the new data
[migrationDict writeToFile:filePath atomically: TRUE];
// ...and the migration is done
}
}
Current NSLog-based output:
2012-09-06 20:57:50.332 xxxx_3[1505:fb03] gameFileDict: {
Barnspelare = (
1,
1,
2,
2,
1,
0
);
"Ton\U00e5rsspelare" = (
2,
0,
0,
0,
0,
0
);
Vuxenspelare = (
3,
1,
0,
2,
0,
1
);
}
2012-09-06 20:57:50.334 xxxx_3[1505:fb03] nrOfKeys: 3
2012-09-06 20:57:50.335 xxxx_3[1505:fb03] xmigrationDict: {
"Ton\U00e5rsspelare" = (
2,
0,
0,
0,
99,
99
);
}
2012-09-06 20:57:50.336 xxxx_3[1505:fb03] migrationDict: {
Barnspelare = (
2,
0,
0,
0,
99,
99
);
"Ton\U00e5rsspelare" = (
2,
0,
0,
0,
99,
99
);
Vuxenspelare = (
2,
0,
0,
0,
99,
99
);
}
2012-09-06 20:57:50.336 xxxx_3[1505:fb03] theObjects: (
2,
0,
0,
0,
0,
0
)
I think that there is a simpler approach to this. Here is a way:
(Assuming that you have fetched your data in a dictionary called d and skipping the parts where you read / write the file...)
NSMutableDictionary *md = [d mutableCopy];
for (NSString *key in d)
{
NSMutableArray *values = [[md valueForKey:key] mutableCopy];
[values addObject:[NSNumber numberWithInt:99]]; // 1st new field
[values addObject:[NSNumber numberWithInt:99]]; // 2nd new field
[md setObject:values forKey:key];
}
And now your new dictionary (the md) contains:
{
Barnspelare = (
1,
1,
2,
2,
1,
0,
99,
99
);
"Ton\U00e5rsspelare" = (
2,
0,
0,
0,
0,
0,
99,
99
);
Vuxenspelare = (
3,
1,
0,
2,
0,
1,
99,
99
);
}

How can I convert a hex string to a hex array?

For example:
I have a string: hexInString = #"0123456789abcdef", and I want to convert it to a hex array like:
{01, 23, 45, 67, 89, ab, cd, ef}
or:
{0123, 4567, 89ab, cdef}
I tried to do like this, but failed with a result of decimal array:
+ (NSMutableArray *)generateHexArrayFrom:(NSString *)hexInString
{
NSMutableArray * hexArray = [[NSMutableArray alloc] init];
int hexStringSize = sizeof(uint_fast32_t) / 2;
for (int x = 0; x <= [hexInString length] - hexStringSize; x += hexStringSize) {
NSScanner * scanner = [[NSScanner alloc] initWithString:[hexInString substringWithRange:NSMakeRange(x, hexStringSize)]];
uint_fast32_t hex;
[scanner scanHexInt:&hex];
[hexArray addObject:[NSNumber numberWithInt:hex]];
}
return [hexArray autorelease];
}
How can I add hex value to NSMutableArray? Or is there type of data to store it?