我有一系列字典,我需要以非常具体的方式进行过滤。最简单的例子就是解释。
假设我有一个包含以下三个词典的数组,其中@“threadId”,@“subject”,@“messageId”是键:
NSDictionary #1:
@"threadId" : @"1234"
@"subject" : @"hello"
@"messageId" : @"0001"
NSDictionary #2:
@"threadId" : @"1234"
@"subject" : @"hello"
@"messageId" : @"0002"
NSDictionary #3:
@"threadId" : @"9101"
@"subject" : @"goodbye"
@"messageId" : @"0005"
我正在考虑任何具有@“threadId”和@“subject”相同值的字典都是重复的,即使@“messageId”不同。因此,我认为字典1和字典2是重复的,我想从上面的数组中删除EITHER字典1或字典2(不是两者)。换句话说,我想将所有三个词典的原始数组过滤成一个包含EITHER词典1和3 OR词典2和3的新数组。
到目前为止,我尝试这样做的所有尝试都导致过多的for循环,我试图通过threadId对字典进行排序和分离......但后来我陷入了比较部分。我已经看过谓词过滤,但看起来它只会删除符合特定条件的对象,这些条件与其他对象的比较无关。 NSSet将无法工作,因为我正在考虑重复的对象实际上并不重复。
我想知道是否有人可以提出进行此过滤的一般策略。
答案 0 :(得分:0)
你可以使用嵌套的for循环来实现它,其中外部循环遍历所有元素(除了最后一个元素),并且内部循环遍历从当前位置到结尾的所有元素。如果找到一对相等的,则可以将内循环中的一个添加到NSMutableSet
。完成后,您只需从数组中删除NSMutableSet
中的所有元素。
答案 1 :(得分:0)
到目前为止,我尝试这样做的所有尝试都导致过度 循环,我试图通过排序和分隔字典 的threadId。
我认为这将是战略,所以你走的是正确的道路。
在伪代码中(不介意语法)我会这样做;
String *threadid, *subject;
// Important: Array must be already sorted (e.g. with a sortDescriptor)
for (NSDictionary *dict in Array)
{
if (threadid == dict.threadid && subject == dict.subject)
{
// mark for removal
}
threadid = dict.threadid;
subject = dict.subject;
}
要删除的标记意味着要添加要移除到新数组的项目,因为在枚举时,您将无法从数组中删除对象。
答案 2 :(得分:0)
这应该有效:
NSArray *array = ...; // Your array of dictionaries
// This is going to be the filtered array:
NSMutableArray *unique = [NSMutableArray array];
// Set to keep track of all threadId/subject combinations added so far:
NSMutableSet *set = [NSMutableSet set];
for (NSDictionary *d in array) {
// Create "sub-dictionary" that contains only the key/value pairs
// for determining uniqueness:
NSDictionary *tmp = [d dictionaryWithValuesForKeys:@[@"threadId", @"subject"]];
// If we have don't have that combination already ...
if (![set containsObject:tmp]) {
// ... add the full dictionary to the new array ...
[unique addObject:d];
// ... and the threadId/subject combination to the set.
[set addObject:tmp];
}
}
答案 3 :(得分:0)
此代码首先对您的词典进行排序,并在检查后是否重复
NSSortDescriptor *sortDescriptor;
//Order by threadId
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"threadId"
ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
NSArray *arrayOrdered = [yourArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSMutableArray *arrayResult = [NSMutableArray array];
NSString* thread = nil;
NSString* subj = nil;
for (NSDictionary*dic in arrayOrdered) {
if ([thread length] == 0 && [subj length] == 0) {
thread = [dic objectForKey:@"threadId"];
subj = [dic objectForKey:@"subject"];
}else{
if ([thread isEqualToString:[dic objectForKey:@"threadId"]]) {
if (![subj isEqualToString:[dic objectForKey:@"subject"]]) {
//We save it
[arrayResult addObject:dic];
}else{
//It´s already kept
NSLog(@"repeated dic");
}
}else{
[arrayResult addObject:dic];
}
}
}
答案 4 :(得分:0)
使用MutableSet进行简单循环,以检查复合键的唯一性。
NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity:messages.count];
NSMutableSet *keysSet = [[NSMutableSet alloc] init];
for (NSDictionary *msg in messages) {
NSString *key = [NSString stringWithFormat:@"%@%@", msg[@"threadId"], msg[@"subject"]];
if (![keysSet containsObject:key]) {
[filteredArray addObject:msg];
[keysSet addObject:key];
}
}