3

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

这是一个非常可怕的尝试,但它是我能弄清楚如何比较 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 与其他对象开始和结束年份匹配的对象。

4

2 回答 2

7

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

一种简单的方法是遍历数组,收集您已经在可变集中看到的开始/结束年份,并且仅在结果中包含您拥有的开始/结束年份组合的项目'尚未添加。

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; }
于 2013-04-26T03:25:48.687 回答
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]];

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

于 2013-04-26T01:56:46.500 回答