比较数组中的对象以查找时间表中的事件冲突

Comparing objects in arrays to find event clashes in a timetable

我有 4 个将显示在学校时间表上的事件对象。我需要检索一组相互冲突的事件,即一个事件的开始时间在另一个事件的开始时间和结束时间之间。为了首先让算法正确,我在时间上使用了 int 而不是 NSDate。

 Event *event = [[Event alloc] init];
    event.courseName = @"Maths";
    event.room = @"405";
    event.startTime = [NSNumber numberWithInt:8];
    event.endTime = [NSNumber numberWithInt:10];
    [eventsStore addObject:event];

    Event *event2 = [[Event alloc] init];
    event2.courseName = @"English";
    event2.room = @"510";
    event2.startTime = [NSNumber numberWithInt:10];
    event2.endTime = [NSNumber numberWithInt:12];
    [eventsStore addObject:event2];

    Event *event3 = [[Event alloc] init];
    event3.courseName = @"Computing";
    event3.room = @"220";
    event3.startTime = [NSNumber numberWithInt:11];
    event3.endTime = [NSNumber numberWithInt:14];
    [eventsStore addObject:event3];

    Event *event4 = [[Event alloc] init];
    event4.courseName = @"Sports";
    event4.room = @"000";
    event4.startTime = [NSNumber numberWithInt:13];
    event4.endTime = [NSNumber numberWithInt:15];
    [eventsStore addObject:event4];

这是我目前找到的冲突:

 int clashCounter = 0;
    Event *curEv = nil, *otherEv = nil;
    for(int i = 0; i < [eventsStore count]; i++)
    {

        curEv = [eventsStore objectAtIndex:i];


        for (int j = 0; j < [eventsStore count]; j++)
        {
            if (j!=i && ![curEv.clashList containsObject:otherEv])
            {
                otherEv = [eventsStore objectAtIndex:j];
                if (curEv.startTime < otherEv.endTime && otherEv.startTime < curEv.endTime)
                {
                    clashCounter++;
                    NSLog(@"Clash: %@ clashes with %@", curEv.courseName, otherEv.courseName);
                    [curEv.clashList addObject:otherEv];
                }
            }
        }
    }

首先创建两个空的 Event 对象。将循环遍历 eventsStore 数组中的每个 Event,将 curEv 设置为 objectAtIndex。然后遍历每个不是 curEv 且其数组中没有 otherEv 的 eventsStore 数组对象。 (每个事件对象都包含一个名为 clashList 的数组,用于与它发生冲突的事件)。如果有冲突,则将 otherEv 添加到 curEv。

当我 运行 我得到:

ClashTest[3393:134117] Clash: English clashes with Computing
ClashTest[3393:134117] Clash: Computing clashes with English
ClashTest[3393:134117] Clash: Sports clashes with Computing

这表明事件冲突已被拾取,但它在第一个实例中存储了一个副本(英语冲突与计算是双向的)。但是当涉及到体育和计算冲突时,它会按预期工作,因为它只显示一次。

我怎样才能让它正常工作? 抱歉,如果这被认为是特定的,我已经弄乱了几个星期并且无论我尝试什么方式都没有太多喜欢。

我相信你可以使用散列映射来存储冲突,在你的第一个 for 循环之前定义它

NSMutableDictionary* clashes = [[NSMutableDictionary alloc] init];

现在,当你找到冲突(你记录它的地方)时,检查冲突是否已经存在,如果不存在,像这样将它添加到冲突字典中(但你应该有一些唯一的事件 ID ,我假设它是一个整数,例如)

NSString* firstHashKey = [NSString stringWithFormat:@"%d", curEv.Id];
NSString* secondHashKey = [NSString stringWithFormat:@"%d", otherEv.Id];

if (([clashes valueForKey:firstHashKey] == nil) && ([clashes valueForKey:secondHashKey] == nil)) {
    clashes[firstHashKey] = @[ curEv, otherEv ];
}
else {
    // It is already added to the clashes dictionary so no need to do it
}

现在,当您想要打印所有碰撞时,只需执行以下操作即可

for (NSString* key in clashes.allKeys) {
    NSArray* value = clashes[key];
    Event* firstEvent = value[0];
    Event* secondEvent = value[1];
    NSLog(@"Clash: %@ clashes with %@", firstEvent.name, secondEvent.name);
}

您可以将第二个循环更改为以 j = i+1 开始(并将第一个循环更改为在 i < [eventsStore count] - 1 处停止)。然后,您将只检查检查过的元素之后的元素。

代码中的问题是在内循环中初始化otherEvent...

    for (int j = 0; j < [eventsStore count]; j++)
    {
        if (j!=i && ![curEv.clashList containsObject:otherEv]) // <-- look
        {
            // this happens too late to properly check the condition above
            otherEv = [eventsStore objectAtIndex:j];

改成这样...

    for (int j = 0; j < [eventsStore count]; j++)
    {
        otherEv = [eventsStore objectAtIndex:j];
        if (j!=i && ![curEv.clashList containsObject:otherEv])
        {

你的逻辑会起作用。 (虽然有很多改进的机会,包括如上所述缩短这个内部循环)。