从NSMutablearray中删除重复值

时间:2013-04-26 00:06:18

标签: objective-c nsarray nsdictionary

我正在尝试从我的排序数组中删除任何重复...我想我可以使用我的另一个问题中的一个例子来做到这一点但事实证明它甚至没有接近工作。

这是一次非常可怕的尝试,但它是我能弄清楚如何在NSMutableArray中比较单个项目(NSDictionary)的两个元素的唯一方法。

这是我的代码示例

我目前有一个排序数组

 NSArray *duplicatesRemovedArray = [sortedArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
        NSDictionary *dictA = a;
        NSDictionary *dictB = b;

        NSString *startYear1 = dictA[kStartYear];
        NSString *finishYear1 = dictA[kFinishYear];
        NSString *allYear1 = [NSString stringWithFormat:@"%@%@",startYear1, finishYear1];
        NSString *startYear2 = dictB[kStartYear];
        NSString *finishYear2 = dictB[kFinishYear];
        NSString *allYear2 = [NSString stringWithFormat:@"%@%@",startYear2, finishYear2];

        return [allYear1 compare:allYear2];

    }];

如果有人对如何创建我所追求的独特项目的NSArray有任何想法,如果你能给我任何建议,代码示例将非常感激

更新:我应该指出我的NSDictionary中还有另一个元素 一个ID ...

所以我不能只比较你列出的例子中的对象......这是我的疏忽。因此,有效的对象看起来像这样

ID: 1234
STARTYEAR: 1999
FINISHYEAR: 2000

所以我需要一些帮助去除对象,其中StartYear和FinishYear匹配其他对象的开始和结束年份。

2 个答案:

答案 0 :(得分:7)

因此,如果我正确理解了您的问题,您希望以一种方式过滤您的数组:如果有多个具有相同年份值的项目(但可能是不同的ID),则结果中只包含其中一项。 / p>

这样做的一个简单方法是迭代数组,收集您已经在可变集中看到的开始/结束年份,并且如果它们具有开始/结束年份的组合,则仅包括结果中的项目你还没有添加。

NSArray *array = @[@{@"ID": @(1234), @"STARTYEAR": @(1999), @"FINISHYEAR": @(2001)},
                   @{@"ID": @(1235), @"STARTYEAR": @(1999), @"FINISHYEAR": @(2001)},
                   @{@"ID": @(1236), @"STARTYEAR": @(1999), @"FINISHYEAR": @(2000)},
                   @{@"ID": @(1237), @"STARTYEAR": @(1999), @"FINISHYEAR": @(2000)}];

NSMutableArray *duplicatesRemoved = [NSMutableArray array];
NSMutableSet *seenYears = [NSMutableSet set];
for (NSDictionary *item in array) {
    //Extract the part of the dictionary that you want to be unique:
    NSDictionary *yearDict = [item dictionaryWithValuesForKeys:@[@"STARTYEAR", @"FINISHYEAR"]];
    if ([seenYears containsObject:yearDict]) {
        continue;
    }
    [seenYears addObject:yearDict];
    [duplicatesRemoved addObject:item];
}
NSLog(@"%@", duplicatesRemoved);

在此示例中,这将产生以下两项:

{ FINISHYEAR = 2001; ID = 1234; STARTYEAR = 1999; }
{ FINISHYEAR = 2000; ID = 1236; STARTYEAR = 1999; }

答案 1 :(得分:1)

如果您不关心保留数组中项目的顺序,那么确保数组中的对象不同的快速简便方法是将数组转换为集合,然后再转换回数组。集合中的元素是不同的和无序的。

以下是一个例子:

NSArray *a = @[@"a", @"b", @"a", @"c", [NSString stringWithFormat:@"%@", @"a"]];
NSLog(@"a is: %@", a);
NSSet *s = [NSSet setWithArray:a];
NSArray *b = [s allObjects];
NSLog(@"b is: %@", s);

以上输出如下:

a is: (
    a,
    b,
    a,
    c,
    a
)
b is: {(
    b,
    c,
    a
)}

因此,b是一个包含a中所有不同对象的数组。执行相同操作的较短版本是:

NSArray *a = @[@"a", @"b", @"a", @"c", [NSString stringWithFormat:@"%@", @"a"]];
NSArray *b = [[NSSet setWithArray:a] allObjects];

如果你关心订单,那么你有两个选择:使用上面的方法然后重新排序对象,或者使用不同的方法。如果您只希望对象保持排序,那么您当然可以对生成的不同对象数组进行排序以恢复排序顺序。或者,如果对数组进行排序,则可以使用排序将导致重复对象彼此相邻的事实。因此,只需扫描数组,将每个元素与后续元素进行比较,如果它们相同,则删除第一个元素。

如果您需要保留一些无法计算的订单,那么您就有点卡住了。您可以复制数组,将上述方法应用于副本,然后使用原始数组来帮助您恢复原始顺序。

  

我需要帮助删除StartYear和FinishYear匹配的对象

这有点复杂,但并不多。考虑通过排序我上面提到的删除重复项的方法。如果使用startYearfinishYear作为键对字典数组进行排序,则应该得到一个数组,其中具有相同开始和结束年份的对象将相邻。也就是说,具有相同开始年份的所有对象将聚集在一起,并且在每个群集内,具有相同完成年份的所有对象将聚集在一起。您可以使用-sortedArrayUsingDescriptors:轻松进行此类排序。以下是你的方法:

NSSortDescriptor *start = [NSSortDescriptor sortDescriptorWithKey:@"startYear" ascending:YES];
NSSortDescriptor *finish = [NSSortDescriptor sortDescriptorWithKey:@"finishYear" ascending:YES];
NSArray *sortedArray = [unsortedArray sortedArrayUsingDescriptors:@[start, finish]];

之后,按上述步骤进行操作 - 扫描数组,将每个项目与后续项目进行比较。如果他们是一样的,什么也不做。如果它们不同,或者如果到达数组的末尾,则将元素复制到新数组中(或将其索引添加到索引集中,或者其他任何内容)。请注意,在扫描时修改相同的数组是一种创建错误的简单方法(如果使用枚举器或快速枚举,则不得修改数组)。这就是我建议将唯一项目复制到新阵列的原因。