包含具有重复值的字典的字典组数组
Posted
技术标签:
【中文标题】包含具有重复值的字典的字典组数组【英文标题】:Group Array of Dictionaries containing Dictionaries with Duplicate Values 【发布时间】:2020-03-23 18:39:34 【问题描述】:我目前正在开发一个分组的 tableView。我让它工作但想将我的传入数组更改为字典以在 tableview 中提供更多有用的信息。 DictionaryHolder 具有所有不同的键,即名称,它包含一个带有“mainTheme”键的字典,其中一些主键匹配,我想将这些匹配的字典编译成数组,然后用新键“subThemes”编译回一个新字典字典集的数组是否包含“mainTheme”的匹配项...我碰壁了,不知道如何解决这个问题,哪种方法最快,因为有时可能会创建和排序很多字典。任何帮助将不胜感激!
-(NSMutableArray*)themesDictFromThemesPlists:(NSMutableArray*)allThemesonDevice
NSMutableDictionary *compiledThemesDictionaryHolder = [[NSMutableDictionary alloc]init];
NSMutableArray *returnedDict = [[NSMutableArray alloc]init];
NSMutableDictionary *mainThemeCompiled = [[NSMutableDictionary alloc]init];
NSMutableDictionary *themePlistDict = nil;
NSString *packageName= nil;
NSString*fullPlistStr = nil;
NSString *themeStringToDeconstruct = nil;
//create dictionary for each theme
NSMutableArray *allPckgNames = [[NSMutableArray alloc]init];
for (NSString *actualName in allThemesonDevice)
themeStringToDeconstruct = actualName;
if ([themeStringToDeconstruct hasSuffix:@".theme"])
themeStringToDeconstruct = [themeStringToDeconstruct stringByReplacingOccurrencesOfString:@".theme" withString:@""];
themeStringToDeconstruct = [themeStringToDeconstruct stringByReplacingOccurrencesOfString:@"_" withString:@" "];
NSArray *theWords = [themeStringToDeconstruct componentsSeparatedByString:@" "];
NSString *nameWithoutTags = [theWords objectAtIndex:0];
//NSLog (@"ICONOMATIC OBJECT AT INDEX 0 %@",newName);
fullPlistStr = [NSString stringWithFormat:@"/Library/Themes/%@/Info.plist",actualName];
themePlistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:fullPlistStr];
packageName = [themePlistDict objectForKey:@"PackageName"];
//NSLog (@"ThemePlistDict: %@",themePlistDict);
//NSLog (@"ICONOMATIC Actual Name : %@ PackageName: %@",actualName,packageName);
if (packageName)
NSMutableDictionary *compiledTheme = [[NSMutableDictionary alloc]init];
[compiledTheme setValue:actualName forKey:@"fullThemeName"];
[compiledTheme setValue:nameWithoutTags forKey:@"themeName"];
[compiledTheme setValue:packageName forKey:@"mainTheme"];
//can add more icons
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"/Library/Themes/%@/icon.png",actualName]])
[compiledTheme setValue:[NSString stringWithFormat:@"/Library/Themes/%@/icon.png",actualName] forKey:@"icon1"];
NSLog (@"Iconomatic ADD compiledTheme %@ ",compiledTheme);
[compiledThemesDictionaryHolder setValue:compiledTheme forKey:actualName];
//[compiledThemesDictionaryHolder addObject:compiledTheme];
[allPckgNames addObject:packageName];
NSLog (@"Iconomatic compiledThemesDictionaryHolder %@ ",compiledThemesDictionaryHolder);
NSLog (@"Iconomatic ALLPckgs: %@",allPckgNames);
/*create Main Dictionary for each package
This is where Ive hit a wall. I need to determine which dictionaries have matching
"mainTheme" keysValues and compile into array of dictionaries to store in new dictionary
(mainThemeCompiled) which will be added into returnDict which is a array that populates the
tableview by keys*/
//NSSet or descriptorByKeys I don't know how to approach this
//NSMutableArray *tempStorage = [[NSMutableArray alloc]init];
for (NSDictionary *themeDict in compiledThemesDictionaryHolder)
NSLog (@"Iconomatic themeDict: %@",themeDict);
[mainThemeCompiled setValue:themeDict forKey:@"package"];
NSLog(@"Iconomatic compiledThemesDictionaryHolder %@",returnedDict);
return returnedDict;
Iconomatic compiledThemesDictionaryHolder
"Bohemic NOIR alt.theme" =
fullThemeName = "Bohemic NOIR alt.theme";
icon1 = "/Library/Themes/Bohemic NOIR alt.theme/icon.png";
mainTheme = BohemicNOIR;
themeName = Bohemic;
;
"Bohemic NOIR badges.theme" =
fullThemeName = "Bohemic NOIR badges.theme";
icon1 = "/Library/Themes/Bohemic NOIR badges.theme/icon.png";
mainTheme = BohemicNOIR;
themeName = Bohemic;
;
"Bohemic NOIR iPad calendar.theme" =
fullThemeName = "Bohemic NOIR iPad calendar.theme";
icon1 = "/Library/Themes/Bohemic NOIR iPad calendar.theme/icon.png";
mainTheme = BohemicNOIR;
themeName = Bohemic;
;
"Bohemic NOIR mask" =
fullThemeName = "Bohemic NOIR mask";
icon1 = "/Library/Themes/Bohemic NOIR mask/icon.png";
mainTheme = BohemicNOIR;
themeName = Bohemic;
;
【问题讨论】:
命名NSMutableArray *returnedDict = [[NSMutableArray alloc]init];
,这是个坏主意。 returnedDicts
(带有“s”)可能会稍微好一些,但仍然如此。你能缩进你的代码吗?也许创建子方法,因为我认为//create dictionary for each theme
部分增加了复杂性,并不是真正需要的。另外,我强烈建议使用自定义对象而不是NSDictionary
,任何键中的错误都会被破坏。你能显示简单的输入和预期的输出吗?
这是有用的输入。我承认我的命名约定有时可能有点古怪,尽管我知道它的含义并且每个生命周期只使用一次 IK 更改为更合适的名称。我将研究使用自定义对象,我通常会在对象未知时使用,但在我的情况下,我确切地知道它们将永远是什么,除非它们为空。我已经更新了我的答案,现在可以正常工作了。谢谢
【参考方案1】:
好的,这就是我的整体解决方案。主要问题是确定字典数组中可用的匹配对象,并通过使用 indexOfObjectsPassingTest 和 enumerateIndexesUsingBlock 解决
-(NSMutableArray*)themesDictFromThemesPlists:(NSMutableArray*)allThemesonDevice
NSMutableArray *compiledThemesDictionaryHolder = [[NSMutableArray alloc]init];
NSMutableArray *returnedArrayOfDicts = [[NSMutableArray alloc]init];
NSMutableDictionary *themePlistDict = nil;
NSString *packageName= nil;
NSString*fullPlistStr = nil;
//create dictionary for each theme
NSMutableArray *allPckgNames = [[NSMutableArray alloc]init];
for (NSString *actualName in allThemesonDevice)
fullPlistStr = [NSString stringWithFormat:@"/Library/Themes/%@/Info.plist",actualName];
themePlistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:fullPlistStr];
packageName = [themePlistDict objectForKey:@"PackageName"];
//NSLog (@"ThemePlistDict: %@",themePlistDict);
//NSLog (@"ICONOMATIC Actual Name : %@ PackageName: %@",actualName,packageName);
if (packageName)
NSMutableDictionary *compiledTheme = [[NSMutableDictionary alloc]init];
[compiledTheme setValue:actualName forKey:@"fullThemeName"];
[compiledTheme setValue:packageName forKey:@"mainTheme"];
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"/Library/Themes/%@/Icon.png",actualName]])
[compiledTheme setValue:[NSString stringWithFormat:@"/Library/Themes/%@/Icon.png",actualName] forKey:@"icon1"];
[compiledTheme setValue:@"prominate" forKey:@"prominate"];
//can add more icons to dict
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"/Library/Themes/%@/icon.png",actualName]])
[compiledTheme setValue:[NSString stringWithFormat:@"/Library/Themes/%@/icon.png",actualName] forKey:@"icon1"];
//can add more icons to dict
//NSLog (@"Iconomatic ADD compiledTheme %@ ",compiledTheme);
//these arrays below should have same indexes to objects but (allPackgNames) can easliy be grouped
[compiledThemesDictionaryHolder addObject:compiledTheme];
[allPckgNames addObject:packageName];
//NSLog (@"Iconomatic compiledThemesDictionaryHolder %@ ",compiledThemesDictionaryHolder);
// NSLog (@"Iconomatic ALLPckgs: %@",allPckgNames);
//create Main Dictionary for each package
NSMutableArray *tempNameArrayToSort = [[NSMutableArray alloc]initWithArray:allPckgNames];
int mainThemesIndex = 0;
for (NSString *mainThemeName in tempNameArrayToSort)
NSMutableDictionary *mainThemeDict = [[NSMutableDictionary alloc]init];
//check for pckg name. Array may contain several matches so remove those at end of loop
if ([allPckgNames containsObject:mainThemeName])
//gather index set of any matches
NSIndexSet *indxs = [compiledThemesDictionaryHolder indexesOfObjectsPassingTest:^BOOL(NSDictionary *dict, NSUInteger idx, BOOL *stop)
return ([dict[@"mainTheme"]isEqualToString:mainThemeName]);
];
//NSLog(@"Iconomatic indexSet %@",indxs);
//enumerate those index sets to grab dictionaries and store in (subThemes)
NSMutableArray *subThemeArray = [[NSMutableArray alloc]init];
[indxs enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop)
// NSLog(@"Iconomatic dict %@ at index %lu",[compiledThemesDictionaryHolder objectAtIndex:idx],idx);
[subThemeArray addObject:[compiledThemesDictionaryHolder objectAtIndex:idx]];
];
//start creating mainDictionary for MainTheme
NSDictionary *themeDict = [compiledThemesDictionaryHolder objectAtIndex:mainThemesIndex];
NSString *fullThemeName = [themeDict objectForKey:@"fullThemeName"];
NSLog (@"ICONOMATIC BUILD~ MainTheme: %@ Dict: %@ subThemes: %@",mainThemeName,themeDict,subThemeArray);
[mainThemeDict setValue:fullThemeName forKey:@"fullThemeName"];
[mainThemeDict setValue:[themeDict objectForKey:@"mainTheme"] forKey:@"themeName"];
UIImage *icon1 = nil;
UIImage *icon2 = nil;
UIImage *icon3 = nil;
UIImage *icon4 = nil;
if ([subThemeArray count] >=1)
[mainThemeDict setValue:subThemeArray forKey:@"themesSubThemes"];
[mainThemeDict setValue:[NSNumber numberWithInt:[subThemeArray count]] forKey:@"themeSubCount"];
for (NSDictionary *subDict in subThemeArray)
NSString *mainthemeIcons = [NSString stringWithFormat:@"/Library/Themes/%@/IconBundles",[subDict objectForKey:@"fullThemeName"]];
if ([subDict objectForKey:@"prominate"])
icon1 = [UIImage imageWithContentsOfFile:[subDict objectForKey:@"icon1"]];
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/com.apple.AppStore-large.png",mainthemeIcons]])
icon1 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.AppStore-large.png",[subDict objectForKey:@"fullThemeName"]]];
icon2 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.Music-large.png",[subDict objectForKey:@"fullThemeName"]]];
icon3 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.MobileSMS-large.png",[subDict objectForKey:@"fullThemeName"]]];
icon4 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.mobilesafari-large.png",[subDict objectForKey:@"fullThemeName"]]];
else
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/com.apple.AppStore-large.png",mainthemeIcons]])
icon1 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.AppStore-large.png",[subDict objectForKey:@"fullThemeName"]]];
icon2 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.Music-large.png",[subDict objectForKey:@"fullThemeName"]]];
icon3 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.MobileSMS-large.png",[subDict objectForKey:@"fullThemeName"]]];
icon4 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.mobilesafari-large.png",[subDict objectForKey:@"fullThemeName"]]];
//nosubthemes
else
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/com.apple.AppStore-large.png",fullThemeName]])
icon1 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.AppStore-large.png",fullThemeName]];
icon2 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.Music-large.png",fullThemeName]];
icon3 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.MobileSMS-large.png",fullThemeName]];
icon4 = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"/Library/Themes/%@/IconBundles/com.apple.mobilesafari-large.png",fullThemeName]];
if (icon1)
[mainThemeDict setValue:icon1 forKey:@"icon1"];
if (icon2)
[mainThemeDict setValue:icon2 forKey:@"icon2"];
if (icon3)
[mainThemeDict setValue:icon3 forKey:@"icon3"];
if (icon4)
[mainThemeDict setValue:icon4 forKey:@"icon4"];
if ([activeIconomaticThemes containsObject:fullThemeName])
[mainThemeDict setValue:[NSNumber numberWithBool:YES] forKey:@"isActive"];
else
[mainThemeDict setValue:[NSNumber numberWithBool:NO] forKey:@"isActive"];
[allPckgNames removeObject:mainThemeName];
//end of creating mainThemeDict
mainThemesIndex = mainThemesIndex+1;
if ([mainThemeDict count])
[returnedArrayOfDicts addObject:mainThemeDict];
//end of (mainTheme in allPackNames)
NSLog(@"Iconomatic returnedArrayOfDicts %@",returnedArrayOfDicts);
return returnedArrayOfDicts;
现在主要主题的输出是
ICONOMATIC BUILD~ MainTheme: Lotus Dark Dict:
fullThemeName = "Lotus Dark Apps";
mainTheme = "Lotus Dark";
subThemes: (
fullThemeName = "Lotus Dark Apps";
mainTheme = "Lotus Dark";
,
fullThemeName = "Lotus Dark Apps (Alternate)";
mainTheme = "Lotus Dark";
,
fullThemeName = "Lotus Dark Calendar";
mainTheme = "Lotus Dark";
,
fullThemeName = "Lotus Dark Icon Effect";
mainTheme = "Lotus Dark";
,
fullThemeName = "Lotus Dark Mask";
mainTheme = "Lotus Dark";
,
fullThemeName = "Lotus Dark Settings";
mainTheme = "Lotus Dark";
,
fullThemeName = "Lotus Dark Widgets";
mainTheme = "Lotus Dark";
)
最后是:
Iconomatic returnedArrayOfDicts (
fullThemeName = "Bohemic NOIR alt.theme";
icon1 = "<UIImage:0x281f48b40 anonymous 300, 300>";
icon2 = "<UIImage:0x281f5f9f0 anonymous 300, 300>";
icon3 = "<UIImage:0x281f5fba0 anonymous 300, 300>";
icon4 = "<UIImage:0x281f5fcc0 anonymous 300, 300>";
isActive = 1;
themeName = BohemicNOIR;
themeSubCount = 7;
themesSubThemes = (
fullThemeName = "Bohemic NOIR alt.theme";
icon1 = "/Library/Themes/Bohemic NOIR alt.theme/icon.png";
mainTheme = BohemicNOIR;
,
fullThemeName = "Bohemic NOIR badges.theme";
icon1 = "/Library/Themes/Bohemic NOIR badges.theme/icon.png";
mainTheme = BohemicNOIR;
,
【讨论】:
以上是关于包含具有重复值的字典的字典组数组的主要内容,如果未能解决你的问题,请参考以下文章