我想做一个奇怪的字典排序。我有非唯一的值和键,并得到这样的东西
NSArray *counts = [@"1",@"2",@"2",@"3",@"6",@"10"];
NSArray *names =[@"Jerry",@"Marge",@"Jerry",@"Marge",@"Jen",@"Mark"];
我想要的输出是按具有唯一名称的计数降序排序列表。我不希望在我的输出数组中降低同一个人的值。输出应该是。
sortedNames=[@"Mark",@"Jen",@"Marge",@"Jerry"]
sortedCounts=[@"10",@"6",@"3",@"2"];
我真的很感激在这方面的一些帮助。
NSMutableArray *userNameArray = [[NSMutableArray alloc] init];
NSMutableArray *countArray = [[NSMutableArray alloc] init];
for (NSDictionary *dict in bigDick) {
NSString *nameString =[dict objectForKey:@"Name"];
NSString *countString =[dict objectForKey:@"Count"];
NSInteger countInt = [countString integerValue];
NSNumber *countNumber =[NSNumber numberWithInt:countInt];
[userNameArray addObject:nameString];
[countArray addObject:countNumber];
}
NSArray *namesAscending =[[userNameArray reverseObjectEnumerator]allObjects];
NSArray *countsAscending=[[countArray reverseObjectEnumerator]allObjects];
// Put the two arrays into a dictionary as keys and values
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:countsAscending forKeys:namesAscending];
// Sort the first array
NSArray *sortedCountArray = [[dictionary allValues] sortedArrayUsingSelector:@selector(compare:)];
// Sort the second array based on the sorted first array
// NSArray *sortedNameArray= [dictionary objectsForKeys:sortedCountArray notFoundMarker:[NSNull null]];
NSMutableArray *nameArray =[[NSMutableArray alloc] init];
for (int i=1; i<sortedCountArray.count; i++) {
NSString *name = [dictionary allKeysForObject:sortedCountArray[i]];
if (sortedCountArray[i]!=sortedCountArray[i-1]) {
[nameArray addObject:name];
}
}
古老的方法是用数字手动对数组进行排序,方法是在每个迭代中搜索最大值,当您找到最大值时,从最大数字索引处的另一个向量中获取名称并将其移动到新向量中......
max = counts[0];
counter = 0;
for (int i=0;i<counts.count;i++)
{
temp = counts[i];
if (max<temp)
max = temp;
counter = i;
}
[new_names addObject: [names objectAtIndex:counter]];
[new_numbers addObject: max];
[numbers removeObjectAtIndex: counter];
[names removeObjectAtIndex:counter];
尝试这样的事情。如果你这样做,它应该可以工作。重要!不要从计入 for 长度的数组中删除 for 中的元素。
你的问题在于你的算法设计,如果你在调试器中一次单步执行一行,你应该看到它做了什么以及哪里出错了。
我们不是来给你写代码的,但让我们看看我们是否可以通过算法的一个步骤来帮助你:
有用的事实:如果您在字典中查找一个键并且该键不存在,则返回值将nil
。
由此:您可以使用字典来跟踪您看到的与迄今为止最高分配对的名字。你得到一个名字,分数对,在字典中查找这个名字 - 如果你得到nil
它是一个具有新高分的新名字。如果不nil
则为当前已知的最高分,因此您可以进行比较和更新。
这是一个粗略的算法,让我们尝试一下。在我们开始之前,让我们定义一些常量,而不是在任何地方都对键使用文字字符串。这样做的好处是我们不会错误键入字符串,编译器会发现我们是否键入了常量名称。这些可以在文件级别或在方法中定义:
const NSString *kName = @"Name";
const NSString *kCount = @"Count";
现在到代码,在某个地方的方法中,我们需要一个字典:
NSMutableDictionary *highScores = [NSMutableDictionary new]; // a single dictionary rather than your two arrays
现在像以前一样开始循环:
for (NSDictionary *dict in bigDict) // same loop as your code
{
并像以前一样提取两个值:
NSString *nameString = dict[kName]; // same as your code, but using modern syntax
NSInteger countInt = [dict[kCount] integerValue]; // condense two lines of your code into one
现在我们可以在字典中查找名称:
NSNumber *currentScore = highScores[nameString]; // get current high score for user, if any
如果名称作为键存在,这将返回当前关联的值 - 在这种情况下是分数,如果没有匹配的键,这将返回nil
。我们可以在单个if
中对此进行测试:
if (currentScore == nil // not seen user before, no high score
|| currentScore.integerValue < countInt) // seen user, countInt is greater
{
如果我们需要添加名称或更新其分数,则上述条件的计算结果将为 true。添加和更新键/值对是相同的操作,所以我们只需要以下行:
highScores[nameString] = @(countInt); // add or update score for user
以及几个大括号来终止if
和for
:
}
}
让我们看看我们有什么:
NSLog(@"Output: %@", highScores);
这输出:
Output: {
Jen = 6;
Jerry = 2;
Marge = 3;
Mark = 10;
}
这是朝着正确方向迈出的一步。(注意:字典没有排序,NSLog
只是按排序顺序显示键。
确保您了解为什么有效,复制代码并对其进行测试。然后尝试设计算法的下一阶段。
如果你遇到困难,你可以问一个新问题,显示你开发的算法和代码,有人可能会提供帮助。如果你这样做,你应该包括一个指向这个问题的链接,这样人们就可以看到历史(并且知道你不是想通过多个问题为你编写一个应用程序!
呵呵
试试这个。
sortedArray = [yourArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
对数组进行排序后,使用以下方法删除重复项。
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray: sortedArray];
NSArray *arrayWithoutDuplicates = [orderedSet array];