匹配重复项的优化算法
|
我已经编写了一个小型实用程序,用于识别iTunes中的重复曲目。
轨道的实际匹配需要很长时间,我想对其进行优化。
我将曲目数据存储在NSMutableDictionary中,该曲目存储单个曲目数据
由trackID键控的NSMutableDictionaries。这些单独的曲目词典有
至少以下几个键:
TrackID
名称
艺术家
持续时间(以毫厘####。####)
要确定是否有任何曲目彼此匹配,我必须检查:
如果两条音轨的持续时间相距不超过5秒
名称匹配
艺术家比赛
对于我而言,执行此操作的较慢方法是使用两个for循环:
-(void)findDuplicateTracks {
NSArray *allTracks = [tracks allValues];
BOOL isMatch = NO;
int numMatches = 0;
// outer loop
NSMutableDictionary *track = nil;
NSMutableDictionary *otherTrack = nil;
for (int i = 0; i < [allTracks count]; i++) {
track = [allTracks objectAtIndex:i];
NSDictionary *summary = nil;
if (![claimedTracks containsObject:track]) {
NSAutoreleasePool *aPool = [[NSAutoreleasePool alloc] init];
NSUInteger duration1 = (NSUInteger) [track objectForKey:kTotalTime];
NSString *nName = [track objectForKey:knName];
NSString *nArtist = [track objectForKey:knArtist];
// inner loop - no need to check tracks that have
// already appeared in i
for (int j = i + 1; j < [allTracks count]; j++) {
otherTrack = [allTracks objectAtIndex:j];
if (![claimedTracks containsObject:otherTrack]) {
NSUInteger duration2 = (NSUInteger)[otherTrack objectForKey:kTotalTime];
// duration check
isMatch = (abs(duration1 - duration2) < kDurationThreshold);
// match name
if (isMatch) {
NSString *onName = [otherTrack objectForKey:knName];
isMatch = [nName isEqualToString:onName];
}
// match artist
if (isMatch) {
NSString *onArtist = [otherTrack objectForKey:knArtist];
isMatch = [nArtist isEqualToString:onArtist];
}
// save match data
if (isMatch) {
++numMatches;
// claim both tracks
[claimedTracks addObject:track];
[claimedTracks addObject:otherTrack];
if (![summary isMemberOfClass:[NSDictionary class]]) {
[track setObject:[NSNumber numberWithBool:NO] forKey:@\"willDelete\"];
summary = [self dictionarySummaryForTrack:track];
}
[otherTrack setObject:[NSNumber numberWithBool:NO] forKey:@\"willDelete\"];
[[summary objectForKey:kMatches]
addObject:otherTrack];
}
}
}
[aPool drain];
}
}
}
对于大型音乐库,这变得相当慢,并且仅使用1
处理器。建议的一种优化是使用块和过程
分批播放的曲目(共100条)。我试过了如果我的代码
最初需要9个小时才能运行,而现在
四核。那仍然太慢了。但是(在这里超过我的薪水等级)
也许有一种方法可以将我需要的所有值存储在“适合堆栈”的C结构中,这样我就不必从速度较慢的内存中获取值。对于我来说,这似乎太低级了,但是如果我有一个例子,我愿意学习。
顺便说一句,我在乐器中对此进行了介绍,ѭ1占了
CPU时间的86.6%。
然后我想我应该将所有持续时间提取到一个排序的数组中,这样我就不会
在字典中查找持续时间值。我觉得那很好
这个想法,但是当我开始执行它时,我想知道如何确定
最佳批次大小。
如果我有以下持续时间:
2 2 3 4 5 6 6 16 17 38 59 Duration
0 1 2 3 4 5 6 7 8 9 10 Index
然后,仅通过遍历数组,我就知道要找到匹配项
索引为0的歌曲的曲目,我只需要将其与歌曲进行比较
直到索引6。太好了,我有第一批。但是现在我必须
从索引1重新开始,只是发现它的批次也应该在
索引6并排除索引0。我假设我在浪费很多
这里的处理周期决定了批次应该是什么/持续时间
火柴。这似乎是一个“设置”问题,但是我们并没有做太多
在我的算法入门课程中。
我的问题是:
1)识别匹配音轨的最有效方法是什么?是吗
类似于上面的内容吗?是否使用脱节和[统一]
设置的操作略高于我的知识水平?是吗
使用NSArray过滤数组?是否有在线资源
描述这个问题和解决方案?
我愿意以任何方式重组轨道字典
(数据结构)效率最高。起初我以为我需要
通过TrackID执行许多查找,但情况不再如此。
2)有没有更有效的方法来解决此问题?你怎么
摇滚明星从第1款转到优化解决方案?
我搜索答案的时间超过了我愿意承认的时间,因此发现
这些有趣但无济于事的答案:
查找重复
查找排序数组中的所有重复项和缺失值
感谢您的任何帮助,您可以提供,
长矛
没有找到相关结果
已邀请:
2 个回复
可扇胆
犁攀富
这是最坏的O(n2)算法(如果每首歌曲的名称,艺术家和时长都相同)。这是最佳情况下的O(n)算法(如果每首歌曲的名称/艺术家/持续时间不同),并且最终会比O(n2)更接近O(n)(最有可能)。