比较数组中的对象以查找时间表中的事件冲突
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])
{
你的逻辑会起作用。 (虽然有很多改进的机会,包括如上所述缩短这个内部循环)。
我有 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])
{
你的逻辑会起作用。 (虽然有很多改进的机会,包括如上所述缩短这个内部循环)。