Array of dictionary value changes is reflect in all the values - ios

I have NSMutableArray and Added NSMutableDictionary
If i update one value for specific row then all the values changes in NSMutableDictionary.
NSIndexPath *qtyIndex
-(void)demoDefaultCartValues{
[dict_CartItems setValue:#"Item 1 KK Demo" forKey:#"DIC_PRODUCT_NAME"];
[dict_CartItems setValue:#" KK Demo" forKey:#"SELLER_NAME"];
[dict_CartItems setValue:#"1" forKey:#"QTY_VALUE"];
[dict_CartItems setValue:#"42" forKey:#"SIZE_VALUE"];
[dict_CartItems setValue:#"1250" forKey:#"PRICE_VALUE"];
[dict_CartItems setValue:#"1500" forKey:#"DISCOUNT_VALUE"];
for (int i = 0; i <= 5; i++) {
[cartListArray addObject:dict_CartItems];
}
}
#pragma mark - DropDown Delegate
-(void)dropDownView:(UIView *)ddView AtIndex:(NSInteger)selectedIndex{
[[cartListArray objectAtIndex:qtyIndexPath.row] setValue:[sizeArrayList objectAtIndex:selectedIndex] forKey:#"QTY_VALUE"];
NSLog(#"What %#",cartListArray);
}
If I update qty 1 to 5 then all dictionary values QTY_Value changes to 5.

Use new Objective-C features (more than 5 years old) to make this more readable. And add six different mutable dictionaries to the array:
NSDictionary* dict = { #"DIC_PRODUCT_NAME":#"Item 1 KK Demo",
#"SELLER_NAME":#" KK Demo",
#"QTY_VALUE": #"1",
etc.
};
for (NSInteger i = 0; i < 6; ++i)
[cartListArray addObject: [dict mutableCopy]];
and later:
-(void)dropDownView:(UIView *)ddView atIndex:(NSInteger)selectedIndex{
cartListArray [qtyIndexPath.row] [#"QTY_VALUE] = sizeArrayList [selectedIndex];
}
cartListArray should be declared as
NSMutableArray <NSMutableDictionary*> *cartListArray;
Now what I would really recommend that you don't store a dictionary at all, but declare a model class. So you don't have to use strings for quantity etc. but NSInteger. Also that cartListArray isn't mutable if you don't want to modify it after it has been initialised. Keep things immutable whenever you can.

This is obvious
when you are adding NSMutableDictionary to array, array have the reference of that dictionary inside.
Now what you are doing is inserting same dictionary multiple times in array. so when you change a single object in array. all the places are get effected. keeping same object of Dictionary always causes this issue.
Solution for this problem is create a new object every time before you insert into array.
Hope it is helpfult to you

The problem is that your code uses the same dictionary and it's a refrence value , so it's a shallow copy of the same one , you may create a new one every iteration
-(void)demoDefaultCartValues{
for (int i = 0; i <= 5; i++) {
NSMutableDictionary*dict_CartItems = [ NSMutableDictionary new];
[dict_CartItems setValue:#"Item 1 KK Demo" forKey:#"DIC_PRODUCT_NAME"];
[dict_CartItems setValue:#" KK Demo" forKey:#"SELLER_NAME"];
[dict_CartItems setValue:#"1" forKey:#"QTY_VALUE"];
[dict_CartItems setValue:#"42" forKey:#"SIZE_VALUE"];
[dict_CartItems setValue:#"1250" forKey:#"PRICE_VALUE"];
[dict_CartItems setValue:#"1500" forKey:#"DISCOUNT_VALUE"];
[cartListArray addObject:dict_CartItems];
}
}
Or you can use copy / mutableCopy
for (int i = 0; i <= 5; i++) {
[cartListArray addObject:[dict_CartItems mutableCopy]];
}

Related

How to sort one array based on the order of its object in another array in objective-c?

I have list which is sorted by user. then I get the list from server again.
some elements might be deleted or added.
I want to sort the new array based on the sorting of the previous array then add new elements.
Example
oldElementList: [1, 4, 2, 8] ---> user set this order
newElementList: [1, 4, 3, 8]
What I want as output is: [1, 4, 8, 3]
Actually element are not numbers they are objects. and when they are gotten from server some of their property values might have changed.
My answer:
for (ElementModel *oldElement in oldElementList) {
for (ElementModel * newElement in newElementList) {
if ([newElement.number isEqualToString: oldElement.number]) {
[sortedArray addObject: newElement];
[newElementList removeObject: newElement];
break;
}
}
}
for (ElementModel *newElement in newElementList) {
[sortedArray addObject: newElement];
}
I don't think my answer is ok, I want to make it better in performance or in any other aspect that I have not considered.
Which sorting algorithm is appropriate depends very much on your data, e.g.:
- Is the data set to be sorted large (only then, a sophisticated algorithms may pay off)?
- Is the data set to be sorted completely random or presorted?
From your description it seems to me that you have a large data set (otherwise any algorithms giving the correct result would be probably fine, including your own that has a O(n^2) complexity), and that it is presorted, i.e. there are only only a few additions and deletions (otherwise it may not be so important to keep the original sorting).
If so, what about the following algorithm (sorry, it is in Swift, but could surely easily be converted to Obj-C):
let old = [1, 4, 2, 7, 8]
let new = [1, 4, 3, 8, 2]
var oldIndexed: [Int: Int] = [:]
for i in 0 ..< old.count {
oldIndexed[old[i]] = i
}
var newIndexed: [Int: Int] = [:]
for i in 0 ..< new.count {
newIndexed[new[i]] = oldIndexed[new[i]] ?? old.count
}
var resultArray: [(Int, Int)] = []
for (key, value) in newIndexed {
resultArray.append((key, value))
}
resultArray = resultArray.sorted { (first, second) -> Bool in
first.1 < second.1
}
let result = resultArray.map{ $0.0 } // Here: [1, 4, 2, 8, 3]
The idea is to give the old data elements an index, and every new data element the same index. This is done by using dictionaries, since there every element can be accessed by its key in O(1). New elements get a larger index (this could also be a counter to make it clearer). Then the new dictionary is converted back to an array, that is then sorted by its index. Eventually, the index is dropped, and the result is ready.
I guess, the complexity of this algorithm is determined by the sort function that should be optimal since it is implemented in the standard library.
EDIT:
I did not program in Obj-C for a long time, but tried it just for fun once more:
NSArray *old = #[#1, #4, #2, #7, #8];
NSArray *new = #[#1, #4, #3, #8, #2];
NSMutableDictionary *oldIndexed = [[NSMutableDictionary alloc] init];
for (int i = 0; i < old.count; i++) {
[oldIndexed setValue:[NSNumber numberWithInt: i] forKey: old[i]];
}
NSMutableDictionary *newIndexed = [[NSMutableDictionary alloc] init];
long counter = old.count;
for (int i = 0; i < old.count; i++) {
NSNumber *oldIndexOfNewValue = oldIndexed[new[i]];
NSNumber *newIndex;
if (oldIndexOfNewValue != nil) {
newIndex = oldIndexOfNewValue;
} else {
newIndex = [NSNumber numberWithLong: counter];
counter++;
}
[newIndexed setValue: newIndex forKey: new[i]];
}
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSArray *allKeysInNewIndexed = newIndexed.allKeys;
for (int i = 0; i < allKeysInNewIndexed.count; i++) {
NSNumber *nextKey = allKeysInNewIndexed[i];
NSArray *nextPair = #[nextKey, newIndexed[nextKey]];
[resultArray addObject: nextPair];
}
NSArray *sortedResultArray;
sortedResultArray = [resultArray sortedArrayUsingComparator: ^NSComparisonResult(NSArray *first, NSArray *second) {
NSNumber *firstIndex = first[1];
NSNumber *secondIndex = second[1];
return [firstIndex compare: secondIndex];
}];
NSMutableArray * result = [[NSMutableArray alloc] init];
for (int i = 0; i < sortedResultArray.count; i++) {
[result addObject: sortedResultArray[i][0]];
}

storing multiples values for particular key in an array of dictionaries not working iOS

i want to have an array which stores dictionaries with some key-value pair like shown below.
add = (
{
ans = abc;
que = Fdgdf;
},
{
ans = hi;
que = hello;
},
{
ans = GM;
que = dosa;
}
)
Here is what i tried.
for (int i=0; i<=[addKeyArray count]; i++) {
[_addDictNewQA setObject:[addKeyarray objectAtIndex:i] forKey:#"que"];
[_addDictNewQA setObject:[addValuesArray objectAtIndex:i] forKey:#"ans"];
[_addArrayNewQA addObject:_addDictNewQA];
}
here addKeyArray is the array which holds all the 'que' elements and addValuesArrray holds all the 'and' elements. but when i set these arrays to dictionary objects and add that dictionary to new array(_addArrayNewQA), it only display the last element like this-
add = (
{
ans = GM;
que = dosa;
},
{
ans = GM;
que = dosa;
},
{
ans = GM;
que = dosa;
}
)
Can anyone please tell me whats wrong in my code. Any help is appreciated.
That is because you are setting values in same object of NSMutableDictionary, also you dont need to have the NSMutableDictionary as global as you are using it in the for loop only.
You need to create new dictionary
for (int i=0; i<=[addKeyArray count]; i++) {
NSMutableDictionary *_addDictNewQA = [NSMutableDictionary new];
[_addDictNewQA setObject:[addKeyarray objectAtIndex:i] forKey:#"que"];
[_addDictNewQA setObject:[addValuesArray objectAtIndex:i] forKey:#"ans"];
}
[_addArrayNewQA addObject:_addDictNewQA];
You need to create a new inner dictionary each iteration. What you are doing is adding the same dictionary over and over and changing its contents so you end up with an array of dictionaries containing the last entry.
for (int i=0; i<=[addKeyArray count]; i++) {
NSDictionary *innerDict = #{
#"que" : addKeyArray[i],
#"ans" : addValuesArray[i]
};
[_addArrayNewQA addObject:innerDict];
}
And remove the _addDictNewQA instance variable.
Create dictionary in for loop. you need to create new dictionary every time. So, create mutable dictionary in for loop and add that dictionary to mutable array (your result array) which must not create (alloc and init) in for loop.
Your code seems that you have created your dictionary outside the for loop.!!

Tricky NSArray iteration

I have an NSArray(mainArray) that contains 28 items and I want to divide that array into 7 arrays containing 4 items each. Is it possible for me to grab the first 4 items from mainArray, add them to a subArray, then grab the NEXT 4 items and add them to the subArray, and so on until I iterate through all 28 items? If it is possible, how?
Here's my mainArray:
{item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18, item19, item20, item21, item22, item23, item24, item25, item26, item27, item28}
I need to change it to this (groupedArray):
{item1, item2, item3, item4}, {item5, item6, item7, item8}, {item9, item10, item11, item12}, {item13, item14, item15, item16}, {item17, item18, item19, item20}, {item21, item22, item23, item24}, {item25, item26, item27, item28}
This is what I've tried:
int i; int j;
for (i=0, j=1; i<28; i++, j*=4 ) {
NSArray *smallArray = [mainArray subarrayWithRange:NSMakeRange(0, j)];
[groupedArray addObjectsFromArray:smallArray];
}
Thanks,
DB
Some of your indexes are off. You want something like this:
NSArray *mainArray = ... // the full array
NSMutableArray *groupedArray = ... // the new array
for (NSUInteger i = 0; i < mainArray.count; i += 4) {
NSArray *smallArray = [mainArray subarrayWithRange:NSMakeRange(i, 4)];
[groupedArray addObjectsFromArray:smallArray];
}
Please note that this code will crash if the number of elements in mainArray isn't a multiple of 4.

How to avoid NSMutable array add object values changes before adding object to NSMutable array?

I am new to Objective C. I had used following code.
for (int i = 0; i < [ValueisFound count]; i++)
{
NSString* ObjectName = [NSString stringWithUTF8String:name];
ObjectName = [[NSClassFromString([NSString stringWithUTF8String:samType]) alloc]init];
NSMutableDictionary* jsonDictionary=[TemplateClass SeparateArray:jsonValue_1 key:[arrayofKeys objectAtIndex:j] index:i];
ObjectName = [TemplateClass JsonPharser:str1 jsonObject:jsonDictionary];
NSMutableArray *samArray=[[NSMutableArray alloc]initWithObjects:[TemplateClass JsonPharser:str1 jsonObject:jsonDictionary], nil];
[manoj_Array addObject:samArray];
[samArray release];
[ObjectName release];
}
While executing for loop:
at i=0, Object has value(number=10), now manoj_Array also has (number=10).
at i=1, Object has value(number=12), now manoj_Array has (number=12,number=12).
But i want the result as manoj_Array has (number=10,number=12). I don't know how that array values are changing to last value.
My mind
samArray and manoj_Array is shared the memory Reference Thats why last value is insert to the manoj_Array
i = 0 value is Store by the address of 1000
i = 1 value is Store by the address of 1002
but manoj_Array share the memory so change the Last value is Added to manoj_Array
You can implement KVO in order to know when a value has changed and handle its behaviour.

Why Rand() always generates random numbers with fixed Unique Group count?

Even though , I execute the below code again & again I get the same Output. But , I think it should not:
int ObjectCount =500;
NSMutableArray *mut_arr = [[NSMutableArray alloc]initWithCapacity:0];
for (int i = 0; i<ObjectCount ; i++)
{
[mut_arr addObject:[NSNumber numberWithInt: rand()%ObjectCount]];
}
NSSet* uniqueSet = [NSSet setWithArray:mut_arr];
NSLog(#"Array of %d objects generates %d Unique Objects",[mut_arr count],[uniqueSet count]);
The output is as follows:
Array of 500 objects generates 317 Unique Objects
Here, Since the array contains random numbers the unique set count should be same again & again for same ObjectCount.
You're not actually generating unique NSNumber objects; some of them are equal.
A NSArray can contain multiple objects that are equal. A NSSet can not. This is why the set created from your array has less objects.
The reason why you're always getting 317 objects is that you're using rand() without seeding: Why do I always get the same sequence of random numbers with rand()?
Consider using arc4random() instead, which is seeding automatically.
Use like this
[mut_arr addObject:[NSNumber numberWithInt:(arc4random() % (ObjectCount-1) + 1)]];

Resources