NSMutableArray:How to allow duplicate values - iphone

I'm reading a JSON code such as:
[{"question_id":"1",
"trigger_value":"Yes",
"question_text":"What is your first name?",
"question_type":"YN"},
{"question_id":"2",
"trigger_value":"Yes",
"question_text":"What is your second name?",
"question_type":"YN"}
]
But once it's set into NSMutableArray, the duplicate values are deleted. I would like to allow them to check the question_type for each question.
NSString *question_id;
NSString *question_text;
NSString *question_type;
while (dicjson = (NSDictionary*)[enumerator nextObject]) {
question_id = [dicjson objectForKey:#"question_id"];
question_type = [dicjson objectForKey:#"question_type"];
[mutjson setObject:question_id forKey:question_type];
}
Would you give me any idea of allowing duplicate values...?
Thanks in advance.

mutjson looks like a mutable dictionary and not a mutable Array.
So yes, in a dictionary object if you are setting the same key, it will overwrite the previous value.
If you need to store dictionary object, create a mutable array and add each object inside that array as a dintionary object...
NSMutableArray *results = [[NSMutableArray alloc] init];
while (dicjson = (NSDictionary*)[enumerator nextObject]) {
question_id = [dicjson objectForKey:#"question_id"];
question_type = [dicjson objectForKey:#"question_type"];
[result addObject:[NSDictionary dictionaryWithObject:question_id forKey:question_type]];
}

You cannot setObject:forKey: in NSMutableArray. You have to use addObject:. Its also much easier to create the array like this:
NSArray *values = [jsonDict allValues];

You are confusing an array for a dictionary. An array can hold duplicate values. A dictionary cannot hold duplicate keys.
The JSON response is an array of dictionaries. The way you've written your code, specifically [mutjson setObject:question_id forKey:question_type]; seems to suggest that you are simply using a dictionary.
If you would like to check the question type for each question, try instead:
NSString *question_type;
for (NSMutableDictionary *dict in dicjson) {
// I would suggest renaming dicjson to something more descriptive, like results
question_type = [dict objectForKey: #"question_type"];
// Do what you would like now that you know the type
}

Related

Moving through a NSDictionary getting objects that you do not know the 'Key' for? IOS

I have a NSDictionary that I get from a webservice. Each object in this dictionary contains an array. I do not know how many objects there are going to be in the NSDictionary, or what the 'Key' for each object is going to be beforehand. I only know that it will be a Dictionary of arrays.
How can I enumerate through the dictionary reading out the name of the Object and its content into arrays?
All my dealings with Dictionaries so far I could use
[anotherDict objectForKey:#"accounts"]
because I know the 'Keys; to expect beforehand.
Many Thanks,
-Code
NSDictionary has the method: enumerateKeysAndObjectsUsingBlock: since iOS 4.0. It's very straightforward, it receives a block object to operate on entries in the dictionary.
An example:
[anotherDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSArray *arr = obj;
//Do something
}
NSDictionary class has an instance method -allKeys which returns an NSArray with NSStrings for all the keys.
Simplest Way WOuld be to fetch allKeys via the allKeys instance method
NSArray *keys = [myDictionary allKeys];
then iterating over dictionary with for each key.
for (NSString *k in keys)
{
id object = [myDictionary objectForKey:k];
}
You can also get keys in order as if values were sorted using
NSArray *sortedKeys = [myDictionary keysSortedByValueUsingSelector:#selector(compare:)];
you can do this :
NSArray * keys = [dictionnary allKeys];
for (NSString *key in keys) {
NSArray *tmp = [dictionnary objectForKey:key];
}
i am not a pro but i know that you can get all the keys of an dictionary
NSLog(#"%#",[Your_Dictionary allKeys]);
This will give an array of keys in that dictionary.

Sorting NSMutableDictionary's data

I am having an NSMutableDictionary with, being filled dynamically. It looks like this:
{
SomeKey = 6;
AnotherKey = 2;
JustAnotherKey = 28;
}
I need to sort this, so it will be like this one:
{
JustAnotherKey = 28;
SomeKey = 6;
AnotherKey = 2;
}
Is there any way to achieve this? Thanks in advance.
No, sorry!
An NSDictionary doesn't support sorting it's keys - you would have to do that yourself.
Get the keys array from your dictionary, sort that and then go through and get the values from your dictionary. Something like :
NSArray *keys = [myDictionary allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingSelector:#selector(compare:)];
NSArray *values = [NSMutableArray array];
for (id key in sortedKeys)
[values addObject:[myDictionary objectforKey:key]];
Now, values are in the correct order.
However, that's quite a lot of work; if you want them sorted, I would look at storing them in an array to start with?
A Dictionary is an unordered set, which means it doesn't have any order of its elements.So even if you insert the first object as say "one":"first value", and then "two":"second value", when you iterate over the keys, you might get it in any random order(eg: "two' and then "one").
However, if all you want is the values in sorted order, you can iterate over all the keys, fetch the values and store it in an array, and then sort them.
NSArray *values=[myDict allValues];
NSMutableArray *sortedKeys=[[NSMutableArray alloc] init];
NSArray *sortedValues = [values sortedArrayUsingSelector:#selector(yourSelector)];
for (val in sortedArray){
NSString *key=(NSString*)[[myDict allKeysForObject:val] objectAtIndex:0];
[sortedKeys addObject:key]
}
This would be starter for getting first the values in sorted order, and then the corresponding keys. (It is not doing any error checks. So beware of OutOfIndex exceptions).
I am not sure how good would be the efficiency of this code be, coz allKeysForObject would be iterating over all the keys.
Instead of using a NSMutableDictionary, you might consider to use a NSMutableArray and populate it with your own model class which contains a property with the key string and a property with the value.
NSMutableArray provides methods to sort these objects.
Is this helpful enough?

Creating a Two-Dimensional Array with Concrete Positions

I need to create a custom array:
In php I would define as follows:
$myarray[100][80] = 1;
But I don't know how to do it in objective-c...
I don't need an array [0][0],[0][1],[0][2], ... I only need concrete positions in this array [80][12], [147][444], [46][9823746],...
The content of these positions always will be = 1;
for this you would use a dictionary rather than an array as they are always 0,1,2 keyed so something along the lines of:
NSNumber *one = [NSNumber numberWithInt:1];
NSString *key = #"80,12";
NSDictionary *items = [NSDictionary dictionaryWithObject:one forKey:key];
Then to pull them out again you would use the objectForKey: method.
You cannot put ints directly into arrays or dictionaries that's why it is wrapped in the NSNumber object. To access the int after getting the NSNumber out of the dictionary you would use something like:
NSNumber tempNum = [items objectForKey:key];
int i = tempNum.intValue;
See the docs here for a full explanation of the NSDictionary class. Hope this helps...
I an not a PHP master but I believe in php arrays are not real arrays they are hash tables right?
Anyway, I think you are looking for NSDictionary or NSMutableDictionary class.
That looks more like a bitset than an array.
Allocating so many cells for that seems useless, so maybe you could revert the problem, and store the positions in an array.
Well in objective c we can use NSMutableArray to define 2-D arrays.
See the following code, it might help you
NSMutableArray *row = [[NSMutableArray alloc] initWithObjects:#"1", #"2", nil];
NSMutableArray *col = [[NSMutableArray alloc] init];
[col addObject:row];
NSString *obj = [[col objectAtIndex:0] objectAtIndex:0];
NSLog(#"%#", obj);

How do I copy individual Nested NSDictionary's from a NSDictionary to a temporary NSMutableDictionary

Ok so I want to create a temporary NSDictionary from a NSDictionary of nested dictionaries, but I want to deep copy individual items(dictionaries) from the top level dictionary.
The end result is to have a filtered dictionary that i can process and discard without effecting the main dictionary.
That sounds really confusing, so how about a little code to show you what I mean, heres the function i'm working on, this is a rough coding layout, but basically complete in its path of process.
I've looked at reference books and various samples online with no joy.
Cheers,
Darren
- (void)setPricingData
{
// get selected lens option
NSDictionary *aOption = [self.lensOptionsDict objectAtIndex:self._lensOptionsIndex];
if ( aOption == nil )
return;
// get selected lens type
NSDictionary *aType = [self.lensTypesDict objectAtIndex:self._lensTypesIndex];
if ( aType == nil )
return;
// get lens option id and variation_id
NSString *option_id = [aOption valueForKey:#"id"];
NSString *option_variation_id = [aOption valueForKey:#"variation_id"];
// create temp dictionary for type pricing selection
int count = [self.lensTypesDict count];
NSMutableDictionary *aPrices = [[NSMutableDictionary alloc] initWithCapacity:count];
// cycle prices for option id and variation_id matches
for ( NSDictionary *item in self.pricesDict )
{
NSString *variation_id = [item valueForKey:#"variation_id"];
NSString *value_id = [item valueForKey:#"value_id"];
// add matches to temp dictionary
if ( [option_variation_id isEqualToString: variation_id] )
{
if ( [option_id isEqualToString: value_id] )
[aPrices addObject: item];
}
}
// get price from temp dictionary for selected lens type index
NSDictionary *price = [aPrices objectAtIndex:self._lensTypesIndex];
if ( price != nil )
{
// assign values to outlet
self.priceAndStockId = [price valueForKey:#"price"];
self.priceSelected = [price valueForKey:#"price"];
}
// release temp dictionary
[aPrices release];
}
It looks like you're mixing up dictionaries with arrays.
Arrays respond to objectAtIndex whereas dictionaries respond to objectForKeys. Remember that an array is a set of cells that you can index into, starting from 0 all the way up to [array count] - 1.
A dictionary is similar to an array, except that a hash function is used as the indexing method. This means that you need a key to get, or set, and object.
Setting an object in an NSMutableDictionary
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
[myDictionary setObject:anObject forKey:aKey];
Or, you can have an array of keys and corresponding array of objects, and do:
NSDictionary *completeDictionary;
completeDictionary = [NSDictionary dictionaryWithObjects:objectArray
forkeys:keyArray count:[keyArray count]];
In either case, you must have keys for objects. This is in contrast to a regular array in which you can simply do
[myArray addObject:myObject];
To get objects from a dictionary, do
myObject = [myDictionary objectForKey:key];
To get objects from an array, do
myObject = [myArray objectAtIndex:anIntegerIndex];
Finally, your original question pertained to deep copying. To have your dictionary keep an object that won't change, ie, a deep copy, you can do the following:
Assuming I want to store a dictionary within a dictionary, and I have an associated key for the top-level dictionary, I can do the following:
I have an NSMutableDictionary, called topLevelDictionary
I have an NSDictionary, called dictionaryTwo
I have an NSString, which is my key, called myKey.
To make a deep copy of dictionaryTwo, I can do
// assuming topLevelDictionary is previously defined
[topLevelDictionary setObject:[[dictionaryTwo copy] autorelease] forKey:myKey];
In this manner topLevelDictionary will contain a copy of dictionaryTwo whereby if dictionaryTwo changes, the object in topLevelDictionary will not.

How can I get the first element in an NSDictionary?

I have an array of NSDictionaries. How can I pull out the first element in the dictionary?
NSArray *messages = [[results objectForKey:#"messages"] valueForKey:#"message"];
for (NSDictionary *message in messages)
{
STObject *mySTObject = [[STObject alloc] init];
mySTObject.stID = [message valueForKey:#"id"];
stID = mySTObject.stID;
}
There is no "first" element in an NSDictionary; its members have no guaranteed order. If you just want one object from a dictionary, but don't care which key it's associated with, you can do:
id val = nil;
NSArray *values = [yourDict allValues];
if ([values count] != 0)
val = [values objectAtIndex:0];
NSDictionaries are unordered, meaning that there are not first or last element. In fact, the order of the keys are never guaranteed to be the same, even in the lifetime of a specific dictionary.
If you want any object, you can get one of the keys:
id key = [[message allKeys] objectAtIndex:0]; // Assumes 'message' is not empty
id object = [message objectForKey:key];
NSArray has a selector named firstObject that simplifies the code and makes it more readable:
id val = [[yourDict allValues] firstObject];
If yourDict is empty val will be nil, so is not necessary to check the dictionary/array size.
Simplest:
[[dict objectEnumerator] nextObject];
According to Apple, calls to allKeys or allValues incur the cost of creating new arrays:
A new array containing the dictionary’s values, or an empty array if
the dictionary has no entries (read-only)
So, an alternative option that does not incur such cost could look like this:
NSString* key = nil;
for(key in yourDict)
{ // this loop will not execute if the dictionary is empty
break; // exit loop as soon as we enter it (key will be set to some key)
}
id object = yourDict[key]; // get object associated with key. nil if key doesn't exist.
Note: If the dictionary is empty, the key will remain nil, and the object returned will also be nil, we therefore don't need special handling of the case where the dictionary is actually empty.
If someone is still looking for answer for this type of situation then can refer this:
// dict is NSDictionary
// [dict allKeys] will give all the keys in dict present
// [[dict allKeys]objectAtIndex:0] will give from all the keys object at index 0 because [dict allKeys] returns an array.
[[dict allKeys]objectAtIndex:0];
If you have NSDictionary named message,
It's pretty simple:
message[[[message allKeys] objectAtIndex:0]];
But you have to be sure (or better check) that your dictionary has at least one element.
Here is how you can check it:
if ([message allKeys] > 0) NSLog(#"%#", message[[[message allKeys] objectAtIndex:0]]);
But NSDictionary has no guaranteed order, so you probably should use this code only if your dictionary has only one element.
[UPDATE]
It's also good idea to use this if you need to get ANY element of dictionary
Try this:
NSDictionary *firstValue = [responseObject objectAtIndex:0];