从阵列比较其对象的属性删除重复(Remove duplicates from array compa

2019-08-03 01:53发布

假设我有一类的事件,它有2个属性:动作(的NSString)和日期(NSDate的)。

而假设我有事件对象的数组。 问题是,“日期”的属性可以匹配。

我需要删除重复的,也就是说具有相同的日期2个不同的对象是重复的。

我可以在字符串或nsdates的任何数组删除重复的,他们很容易比较。 但如何与复杂的对象,他们的性能进行比较做呢?

不要问我什么,我做了到目前为止,COS'在我心中未来的唯一事情是一个冒泡排序, 但它是一个新手的解决方案,和缓慢的

颇为任何帮助,高度赞赏(链接,TUTS,代码)。

提前致谢。

编辑

由于dasblinkenlight,我做了一个自定义的方法:

- (NSArray *)removeDuplicatesInArray:(NSArray*)arrayToFilter{

    NSMutableSet *seenDates = [NSMutableSet set];
    NSPredicate *dupDatesPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) {
        YourClass *e = (YourClass*)obj;
        BOOL seen = [seenDates containsObject:e.propertyName];
        if (!seen) {
            [seenDates addObject:e.when];
        }
        return !seen;
    }];
    return [arrayToFilter filteredArrayUsingPredicate:dupDatesPred];
} 

这里YourClass是对象所属的类的名称, propertyName是对象你要比较的财产。

假设self.arrayWithObjects包含YourClass的对象。

填充它后,使用

self.arrayWithObjects = [self removeDuplicatesInArray:self.arrayWithObjects];

和你做。

所有学分dasblinkenlight。 干杯!

Answer 1:

您可以创建一个NSMutableSet日期,重复你的事件列表,和只添加事件,你有没有遇到过的日期。

NSMutableSet *seenDates = [NSMutableSet set];
NSPredicate *dupDatesPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) {
    Event *e = (Event*)obj;
    BOOL seen = [seenDates containsObject:e.date];
    if (!seen) {
        [seenDates addObject:e.date];
    }
    return !seen;
}];
NSArray *events = ... // This is your array which needs to be filtered
NSArray *filtered = [events filteredArrayUsingPredicate:dupDatesPred];


Answer 2:

不会与KVC这项工作。 我想下面的解决方案可以在你的情况下工作;

Event *event1 = [[Event alloc] init];
event1.name = @"Event1";
event1.date = [NSDate distantFuture];
Event *event2 = [[Event alloc] init];
event2.name = @"Event2";
event2.date = [NSDate distantPast];
Event *event3 = [[Event alloc] init];
event3.name = @"Event1";
event3.date = [NSDate distantPast];
NSArray *array = @[event1, event2, event3];

NSArray *filteredEvents =  [array valueForKeyPath:@"@distinctUnionOfObjects.name"];


Answer 3:

NSMutableArray *leftObjects = [duplicateArray mutableCopy];
NSMutableArray *nonDuplicates = [NSMutableArray new];
while (leftObjects.count > 0)
{
    YourClass *object = [leftObjects objectAtIndex:0];

    // find all objects matching your comaprison equality definition for YourClass
    NSArray *matches = [leftObjects filteredArrayUsingPredicate:
                        [NSPredicate predicateWithBlock:^BOOL(YourClass *evaluatedObject, NSDictionary *bindings)
                         {
                             return (evaluatedObject.name == object.name);
                         }] ];
    [leftObjects removeObjectsInArray:matches];

    // add first object (arbitrary, may decide which duplicate to pick)
    [nonDuplicates addObject:matches.firstObject];
}


Answer 4:

我认为最有效的方法是使用NSDictionary存储对象值和属性值作为重点,并添加任何对象字典,然后检查是否存在与否是O(1)操作,即全过程将O(n)的

下面是代码

- (NSArray *)removeDuplicatesFromArray:(NSArray *)array onProperty:(NSString *)propertyName {
    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];

    for (int i=0; i<array.count; i++) {

        NSManagedObject *currentItem = array[i];
        NSString *propertyValue = [currentItem valueForKey:propertyName];

        if ([dictionary valueForKey:propertyValue] == nil) {
            [dictionary setValue:currentItem forKey:propertyValue];
        }
    }

    NSArray *uniqueItems = [dictionary allValues];

    return uniqueItems;
}

你可以使用它作为以下

self.arrayWithObjects = [self removeDuplicatesFromArray:self.arrayWithObjects onProperty:@"when"]; 


Answer 5:

这里是NSArray类,消除指定属性重复迅捷的扩展:

extension NSArray {
/**
 - parameter property: the name of the property to check for duplicates

 - returns: an array of objects without objects that share an identical value of the specified property
*/
  func arrayWithoutObjectsOfDuplicateProperty(property : String) -> [AnyObject] {
    var seenInstances = NSMutableSet()

    let predicate = NSPredicate { (obj, bind) -> Bool in
      let seen = seenInstances.containsObject(obj.valueForKey(property)!)

      if !seen {
        seenInstances.addObject(obj.valueForKey(property)!)
      }
        return !seen
      }      
      return self.filteredArrayUsingPredicate(predicate)
  }
}


Answer 6:

这里正在剪断夫特代码不删除重复,同时保持元素的顺序

// Custom Struct. Can be also class. 
// Need to be `equitable` in order to use `contains` method below
struct CustomStruct : Equatable {
      let name: String
      let lastName : String
    }

// conform to Equatable protocol. feel free to change the logic of "equality"
func ==(lhs: CustomStruct, rhs: CustomStruct) -> Bool {
  return (lhs.name == rhs.name && lhs.lastName == rhs.lastName)
}

let categories = [CustomStruct(name: "name1", lastName: "lastName1"),
                  CustomStruct(name: "name2", lastName: "lastName1"),
                  CustomStruct(name: "name1", lastName: "lastName1")]
print(categories.count) // prints 3

// remove duplicates (and keep initial order of elements)
let uniq1 : [CustomStruct] = categories.reduce([]) { $0.contains($1) ? $0 : $0 + [$1] }
print(uniq1.count) // prints 2 - third element has removed

而就如果你想知道如何减少神品 - 在这里是完全一样的,但使用更加扩大减少语法

let uniq2 : [CustomStruct] = categories.reduce([]) { (result, category) in
  var newResult = result
  if (newResult.contains(category)) {}
  else {
    newResult.append(category)
  }
  return newResult
}
uniq2.count // prints 2 - third element has removed

你可以简单地复制粘贴此代码到一个斯威夫特游乐场和玩。



文章来源: Remove duplicates from array comparing the properties of its objects