【问题标题】:remove duplicate valuse from NSMutable array [duplicate]从 NSMutablearray 中删除重复值 [重复]
【发布时间】:2013-04-20 01:15:57
【问题描述】:

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

这是一个非常可怕的尝试,但这是我能弄清楚如何比较 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: 1234
STARTYEAR: 1999
FINISHYEAR: 2000

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

【问题讨论】:

标签: objective-c nsarray nsdictionary


【解决方案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]];

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

【讨论】:

  • 我刚刚完成了一些阅读,其中我看到你可以将对象作为一个整体相互比较......我没有想到的事情是可能的,在我最初的问题中我忽略了另一个元素在 NSDictionary 中,认为删除基于 startYear finishYear 的重复项没有任何影响。看起来您提供了一个类似的解决方案,在您提交答案之前的一两分钟,我已经更新了我的问题以定义我的脸在我的 NSDictionary 中有一个唯一的元素值..
  • 哎呀..刚刚在玩代码..我没有看到你的更新..现在要阅读:)
  • 该死的!!!您的引述“我需要一些帮助来删除与 StartYear 和 FinishYear 匹配的对象”是完全正确的,但我的措辞完全错误....该死的实际上应该是我想删除与其他对象匹配的 startYear 和 finishyear 对象在数组中。所以换句话说,数组的每个对象都相互比较,所以最后你有一个对象数组,数组中有唯一的 startyear 结束年对象。我非常希望这是有道理的。
  • @C.Johns 这正是我描述的方法。
  • 哦,它只是我已经尝试了你的例子,我得到了一个唯一的对象数组,它不是 startyear 完成年唯一的,因为数组中有一个 ID 元素。所以我发现我还在重复年...我会再次查看您的答案,看看我是否遗漏了什么..感谢您的耐心
【解决方案2】:

因此,如果我正确理解了您的问题,您希望以一种方式过滤您的数组,如果有多个项目具有相同的年份值(但可能是不同的 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; }

【讨论】:

  • 是的,这正是我想要达到的目标。我现在就试试你的答案,让你知道我的进展。
  • 天哪……它奏效了。伙计,我已经多次回到这个问题上,希望在某一时刻我能理解并解决它,或者有人能理解我的要求并帮助我.. 非常感谢....我非常感谢你的帮助.. 哦,伙计.. 解决这个问题感觉真好... 非常感谢!
猜你喜欢
  • 2011-08-24
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 2014-01-20
相关资源
最近更新 更多