I have a record of 100 Electronic items with Categories in database, with every request I load 20 records in Table View. I want to merge 2 arrays into 3rd array
E.g.
1) NSMutableDictionary *prevResultSet;
2) NSMutableDictionary *newResultSet;
3) NSMutableDictionary *finalArray;
I tried using addEntriesFromDictionary but it overwrites the duplicate key instead of merging.
_finalArray = [[NSMutableDictionary alloc] init];
[_finalArray addEntriesFromDictionary:_prevResultSet];
[_finalArray addEntriesFromDictionary:_newResultSet];
_prevResultSet = {
LED = (
{
rate = "25,000";
type = Sony;
},
{
rate = "25,000";
type = Samsung;
},
);
LCD = (
{
rate = "15,000";
type = Samsung;
},
{
rate = "15,000";
type = Sony;
},
);
_newResultSet = {
LCD = (
{
rate = "15,000";
type = LG;
},
{
rate = "15,000";
type = Onida;
},
);
Current Output: (After using addEntriesFromDictionary:)
_finalArray = {
LED = (
{
rate = "25,000";
type = Sony;
},
{
rate = "25,000";
type = Samsung;
},
);
LCD = (
{
rate = "15,000";
type = LG;
},
{
rate = "15,000";
type = Onida;
},
);
Expected Output:
_finalArray = {
LED = (
{
rate = "25,000";
type = Sony;
},
{
rate = "25,000";
type = Samsung;
},
);
LCD = (
{
rate = "15,000";
type = Samsung;
},
{
rate = "15,000";
type = Sony;
},
{
rate = "15,000";
type = LG;
},
{
rate = "15,000";
type = Onida;
},
);
Thanks in advance...
Check for each key in newResultSet if it exists and merge or add the array.
NSMutableDictionary *finalDictionary = [prevResultSet mutableCopy];
[newResultSet enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSArray *array = finalDictionary[key];
if (array)
finalDictionary[key] = [array arrayByAddingObjectsFromArray:obj];
else
finalDictionary[key] = obj;
}];
Well, this is expected.
From the Documentation, addEntriesFromDictionary tells that:
If both dictionaries contain the same key, the receiving dictionary’s
previous value object for that key is sent a release message, and the
new value object takes its place.
You need to use setObject to add each object to the dictionary.YOu need to loop through the keys of one dictionary and add it to the final dictionary.
Even setObject tells the same:
The key for value. The key is copied (using copyWithZone:; keys must
conform to the NSCopying protocol). If aKey already exists in the
dictionary, anObject takes its place.
You cannot have two same keys in the dictionary. All keys in the dictionary are unique.
If you still want to have the same key-value in the dictionary, you must use a different key.
For example, you have two dictionaries with following values:
NSDictionary *dict1=#{#"hello":#"1",#"hello2" :#"2"};
NSDictionary *dict2=#{#"hello":#"1",#"hello2":#"2",#"hello3":#"1",#"hello6":#"2",#"hello4":#"1",#"hello5" :#"2"};
NSMutableDictionary *mutableDict=[NSMutableDictionary dictionaryWithDictionary:dict1];
for (id key in dict2.allKeys){
for (id subKey in dict1.allKeys){
if (key==subKey) {
[mutableDict setObject:dict2[key] forKey:[NSString stringWithFormat:#"Ext-%#",key]];
}else{
[mutableDict setObject:dict2[key] forKey:key];
}
}
}
and by the end of this loop, your new mutable dictionaries will have the follwoing key-values:
{
"Ext-hello" = 1;
"Ext-hello2" = 2;
hello = 1;
hello2 = 2;
hello3 = 1;
hello4 = 1;
hello5 = 2;
hello6 = 2;
}
As you can see, hello, and hello2 keys are renamed as Ext-hello1, Ext-hello2. form the dict1, and you still have all the dict2 values added to your mutable dict.
IF you don't want to add a new key, then you can add the values into an arrya and add that array to the dictionary. YOu can modify the for-loop to:
for (id key in dict2.allKeys){
for (id subKey in dict1.allKeys){
if (key==subKey) {
NSMutableArray *myArr=[[NSMutableArray alloc]init];
[myArr addObject:dict1[subKey]];
[myArr addObject:dict2[key]];
[mutableDict setObject:myArr forKey:key];
}else{
[mutableDict setObject:dict2[key] forKey:key];
}
}
}
And now you will have the values merged into an array:
{
hello = (
1,
1
);
hello2 = 2;
hello3 = 1;
hello4 = 1;
hello5 = 2;
hello6 = 2;
}
In this way, the number of keys will be same, and the values for the same key will be added as an array.
Related
I have a class in swift which makes the dictionary using strings in keys and objects in values. eg let dict = ["key":value.key]. the value is always a string.
When i get the data in my objective c class, for one the object type is
_TtGCs26_SwiftDeferredNSDictionaryVs11AnyHashableP__$
and the code is expecting nsdictionary.
Now when the code -
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionaryFromSwiftClass];
is executed, the program throws the error
********[1235:641121] -[__SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x280571380
//making dict in swift class
let dictForAddToCart:NSDictionary =
[
"assoc_prod":[
["assoc_prodID":"92",
"assoc_prodValue":currentSelectedColor,
"productInfo":[
"code":productInfoColor.value(forKey: "code"),
"id":productInfoColor.value(forKey: "id"),
"image":productInfoColor.value(forKey: "image"),
"label":productInfoColor.value(forKey: "label"),
"optionslabel":productInfoColor.value(forKey: "optionslabel"),
"price":productInfoColor.value(forKey: "price"),
"qty":productInfoColor.value(forKey: "qty")]],
["assoc_prodID":"92",
"assoc_prodValue":currentSelectedColor,
"productInfo":[
"code":productInfoColor.value(forKey: "code"),
"id":productInfoColor.value(forKey: "id"),
"image":productInfoColor.value(forKey: "image"),
"label":productInfoColor.value(forKey: "label"),
"optionslabel":productInfoColor.value(forKey: "optionslabel"),
"price":productInfoColor.value(forKey: "price"),
"qty":productInfoColor.value(forKey: "qty")]]
]
"productData":productData,
"qty":currentSelectedQuantity
] as NSDictionary
//saving object in objective c class
- (void)saveCartArray:(NSArray *)arrayToSave {
NSMutableArray *archiveArray = [NSMutableArray arrayWithCapacity:arrayToSave.count];
for (NSMutableDictionary* productDic in arrayToSave) {
NSData *productDicData = [NSKeyedArchiver archivedDataWithRootObject:productDic];
[archiveArray addObject:productDicData];
}
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
[userData setObject:archiveArray forKey:#"cart"];
}
//NSLOG of arrayToSave-
{
"assoc_prod" = (
{
"assoc_prodID" = 92;
"assoc_prodValue" = 396;
code = "********.Code.color";
id = 92;
image = "********.Image.empty";
label = "********.Label.color";
optionslabel = Nude;
price = "280.0000";
qty = "0.0000";
},
{
"assoc_prodID" = 180;
"assoc_prodValue" = 388;
code = "********.Code.size";
id = 180;
image = "********.Image.empty";
label = "********.Label.size";
optionslabel = 36;
price = "280.0000";
qty = "0.0000";
}
);
productData = {
additionalParameters = (
);
associatedProd = "someData";
brand = "";
categoryId = 378;
description = "";
image = "http://www.x.com/xyz.jpg";
link = "";
linkDownloads = "";
name = some;
position = 0;
price = 280;
productId = 1421;
qty = 0;
set = 0;
shortDescription = "";
sku = some;
type = some;
wsp = "";
};
qty = 1;
}
)
I have a hunch this is a similar problem I answered here:
https://stackoverflow.com/a/53501401/5329717
Your case would be slightly different due to this:
- (void)saveCartArray:(NSArray *)arrayToSave {
NSMutableArray *archiveArray = [NSMutableArray arrayWithCapacity:arrayToSave.count];
for (NSMutableDictionary* productDic in arrayToSave) {
NSData *productDicData = [NSKeyedArchiver archivedDataWithRootObject:productDic];
[archiveArray addObject:productDicData];
}
So essentially if I understand correctly the Swift bridged SwiftDeferredNSDictionary are elements in NSArray*.
If you could extract
NSData *productDicData = [NSKeyedArchiver archivedDataWithRootObject:productDic];
to a separate method something like:
-(NSData*)dictionaryToData:(NSDictionary*)dic {
return [NSKeyedArchiver archivedDataWithRootObject:productDic];
}
And use my linked answer workaround:
func mySwiftFunc(dic: Dictionary) {
myObjcClassInstance.perform(#selector(NSSelectorFromString("dictionaryToData:"), with: dic as NSDictionary)
}
You could ensure you deal with "real" NSDictionary and avoid the implicit __SwiftValue bridging.
A NSMutableArray called arrayDB, and it gets data from server by using AFNetworking, like this
[self.arrayDB addObjectsFromArray:[responseObject objectForKey:#"list"]];
NSLog(#"print:%#",self.arrayDB);
And the result like this.
print:(
{
id = 10;
key = 7707eca6ea4d2db923c8b7b4e6ec094c;
},
{
id = 9;
key = 7aaf962bc4df61a3b44c544c58fc6c82;
},
{
id = 7;
key = ce9d9e99a96d6417c6b34321c820c4c0;
},
{
id = 6;
key = 6086663465e5813d08f862eb443e2623;
},
{
id = 4;
key = 5d9519dd7de26f0139d6028fb83a4ead;
}
)
And now, I use sql statement to describe my needs, select key from arrayDB where id=10, how can I write in objective-C?
You can use NSPredicate like this:
NSArray *myArray = [self.arrayDB filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(id == %#)", #"10"]];
I have a json array that I'm trying to extract data from. The array was created using NSJSONSerialization. Here is what the json array looks like from NSLog([jsonArray debugDescription]);:
{
properties = (
{
ID = 12345;
PropertyName = "McDonalds";
key = 00112233445566778899aabbccddeeff;
},
{
ID = 12346;
PropertyName = "Taco Bell";
key = 00112233445566778899aabbccddeef0;
},
{
ID = 12347;
PropertyName = "Burger King";
key = 00112233445566778899aabbccddeef1;
}
);
success = 1;
totalCount = 3;
}
I need to extract each ID and each Property name and dump the values into separate arrays. How can I do this?
You can use Key-Value Coding:
NSArray *ids = [jsonArray valueForKeyPath:#"properties.ID"];
NSArray *propertyNames = [jsonArray valueForKeyPath:#"properties.PropertyName"];
Is there a way to directly access an inner-Dictionary of an outer Dictionary in Objective-C? For example, I have key to an object which is part of inner dictionary, Is there any way to directly access object from that key.
GameDictionary {
Indoor_Game = { "game1" = chess; "game2" = video_Game; "game3" = poker; };
OutDoor_Game = { "game4" = cricket; "game5" = hockey; "game6" = football; };
};
I have a key "game4", but I don't know in which dictionary object of this key is present, currently I have to search in each dictionary for object, the code which I am using is:
NSString* gameName = nil;
NSString* gameKey = #"game4";
NSArray* gameKeys = [GameDictionary allKeys];
for (int index = 0; index < [gameKeys count]; index ++) {
NSDictionary* GameType = [GameDictionary objectForKey:[gameKeys objectAtIndex:index]];
if ([GameType objectForKey:gameKey]) {
gameName = [GameType objectForKey:gameKey];
break;
}
}
Is their any easy way to access directly to the inner dictionary instead of for loops.
valueForKeyPath looks like what you want.
[GameDictionary valueForKeyPath:#"OutDoor_Game"]
//would return a dictionary of the games - "game4" = cricket; "game5" = hockey; "game6" = football;
[GameDictionary valueForKeyPath:#"OutDoor_Game.game4"]
//would return cricket
https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html
I have a structured array like the one below
(
{
id = 0;
name = "A";
tables = (
{
comment = "";
id = 0;
name = "T1";
},
{
comment = "";
id = 1;
name = "T2";
},
{
comment = "";
id = 4;
name = "T3";
}
);
},
{
id = 1;
name = "B";
tables = (
{
comment = "";
id = 5;
name = "T1";
},
{
comment = "";
id = 6;
name = "T2";
}
);
}
)
Given that I know the value of id key of one of the dictionaries (let's take id=6), how can I get its parent dictionary or to be more precise the value of name key (in this case B).
I've tried using predicate strings but the problem is that the parent dictionary has also a key named id, so I get the wrong results.
EDIT: id keys are unique (and it is also not necessary that ids of the elements in the first dictionary have lower intiger values than the ones in the dictionaries with higher indexes)
Try this, where array is your structured array
NSDictionary *parentDict=[[NSDictionary alloc]initWithDictionary:nil];
NSString *name=[[NSString alloc]init];
NSArray *table=[[NSArray alloc]initWithArray:nil];
for (NSDictionary * dict in array) {
table=[dict objectForKey:#"tables"];
for (NSDictionary *childDict in table) {
if ([[childDict objectForKey:#"id"]isEqualToString:#"6"]) {
//if your id value is int then use ==6 to check
parentDict=dict;
name=[dict objectForKey:#"name"];
return;
}
}
}