在接受iOS开发职位采访时,他们向我询问了最快的解决方案,找到大型数据中的已删除项目(> 100万项),即:在本地,应用程序有来自服务器的数组(我们不在乎)关于从服务器获取此数组的方法)。然后,在服务器上,他们删除了此阵列中的几个项目。在当地,我们不知道。那么,我们如何在本地找到已删除的项目,基于服务器上的新阵列和本地阵列? 我想在02天之后&在下面找到这个循环但是当服务器在数组的开头或结尾删除了项目时它就可以了。当在数组中间删除项目时,此循环需要很长时间才能完成。
#define rchar (rand() % ('z'-'a') + 'a')
- (void)viewDidLoad:
NSMutableArray * mar = [NSMutableArray new]; // represent server array.
for (int i = 0; i<50000; i++) //10 50000 200000 400000 600000 800000
{
NSString * str = [NSString stringWithFormat:@"%c%c%c%c",rchar, rchar, rchar, rchar];
[mar addObject:str];
}
NSMutableArray *tmpServerArr = [[NSMutableArray alloc] initWithArray:mar copyItems:YES];
NSMutableArray *localArr = [[NSMutableArray alloc]initWithCapacity:50002]; // represent local array
for (int i = 0; i<50002; i++) //10 50000 200000
{
switch (i) {
case 32111: [localArr addObject:[NSString stringWithFormat:@"%c%c%c%c",rchar, rchar, rchar, rchar]];
break;
case 41234: [localArr addObject:[NSString stringWithFormat:@"%c%c%c%c",rchar, rchar, rchar, rchar]];
break;
case 50000: [localArr addObject:mar[32111]];
break;
case 50001: [localArr addObject:mar[41234]];
break;
default: [localArr addObject:mar[i]];
break;
}
}
NSUInteger localremainItem = [localArr count];
NSDate *start;
NSUInteger loopWhile = 0;
while (localremainItem > 0 ) {
// while ([localArr count] > 0 ) {
NSUInteger idxItemStr = (localremainItem -1 - pow(-1, loopWhile)*(localremainItem-1))/2; // -1;
NSLog(@"idxstring: %li -- pow: %f", idxItemStr, pow(-1, loopWhile));
NSString *itemStr = localArr[idxItemStr];
NSLog(@"item checked : %@]", itemStr);
NSPredicate *pre = [ NSPredicate predicateWithFormat:@"NOT (SELF like %@)", itemStr];
NSCountedSet * localCountedSet = [[ NSCountedSet alloc] initWithArray:localArr];
NSCountedSet * serverCountedSet = [[ NSCountedSet alloc] initWithArray:tmpServerArr];
if ([localCountedSet countForObject:itemStr] > [serverCountedSet countForObject:itemStr]) {
NSLog(@"this item %@ was deleted in server.", itemStr);
}
//else {
[localArr filterUsingPredicate: pre];
[tmpServerArr filterUsingPredicate:pre];
NSLog(@"localremain: %li", [localArr count]);
NSLog(@"tmpserverremain: %li", [tmpServerArr count]);
// }
if ([localArr count] == [tmpServerArr count]) {
localremainItem = 0;
}
else localremainItem = [localArr count];
loopWhile +=1;
}
NSLog(@"now server arr is controled! time: %f", -[start timeIntervalSinceNow]);
感谢您的帮助
** 2015年11月14日更新:以下循环速度快8倍:
在viewDidLoad中:
while ([localArr count] >0) {
NSUInteger maxRange =0;
if ([localArr count] >500) {
maxRange = 500;
}else maxRange = [localArr count];
NSArray *sampleTest = [[NSArray alloc] initWithArray:[localArr subarrayWithRange:NSMakeRange(0,maxRange)]];
NSLog(@"sampleTest cnt: %lu", (unsigned long)[sampleTest count]);
if ([self countSampleTest:localArr serverArr:tmpServerArr sampleTest:sampleTest]) {
NSPredicate *pre = [ NSPredicate predicateWithFormat:@"NOT (SELF in %@)", sampleTest];
[localArr filterUsingPredicate: pre];
[tmpServerArr filterUsingPredicate:pre];
NSLog(@"localremain: %li", [localArr count]);
NSLog(@"tmpserverremain: %li", [tmpServerArr count]);
}
else {
NSLog(@"deleted item in here!: %i, %li", 0, [sampleTest count]); //[localArr count]/10);
int found = 0;
while (found <10) {
maxRange =0;
if ([localArr count] >50) {
maxRange = 50;
}else maxRange = [localArr count];
NSArray *sampleTest1 = [[NSArray alloc] initWithArray:[localArr subarrayWithRange:NSMakeRange(0,maxRange)]];
NSLog(@"sampleTest1 cnt: %lu", (unsigned long)[sampleTest1 count]);
if ([self countSampleTest:localArr serverArr:tmpServerArr sampleTest:sampleTest1]) {
NSPredicate *pre = [ NSPredicate predicateWithFormat:@"NOT (SELF in %@)", sampleTest1];
[localArr filterUsingPredicate: pre];
[tmpServerArr filterUsingPredicate:pre];
NSLog(@"localremain: %li", [localArr count]);
NSLog(@"tmpserverremain: %li", [tmpServerArr count]);
}
else {
NSUInteger k = 0;
while (k< [sampleTest1 count]) {
NSLog(@"item checked %lu : %@]", (unsigned long)k, sampleTest1[k]);
NSCountedSet * localCountedSet = [[ NSCountedSet alloc] initWithArray:localArr];
NSCountedSet * serverCountedSet = [[ NSCountedSet alloc] initWithArray:tmpServerArr];
if ([localCountedSet countForObject:sampleTest1[k]] > [serverCountedSet countForObject:sampleTest1[k]]) {
NSLog(@"this item %@ was deleted in server.", sampleTest1[k]);
}
NSPredicate *pre = [ NSPredicate predicateWithFormat:@"NOT (SELF like %@)", sampleTest1[k]];
[localArr filterUsingPredicate: pre];
[tmpServerArr filterUsingPredicate:pre];
NSLog(@"localremain: %li", [localArr count]);
NSLog(@"tmpserverremain: %li", [tmpServerArr count]);
if ([localArr count] == [tmpServerArr count]) {
k = [sampleTest1 count];
found = 10;
}else k +=1;
}
}
found +=1;
}
}
if ([localArr count] == [tmpServerArr count]) {
localArr = nil;
}
// if ([sampleTest count] == 0) {
// localArr = nil;
// }
}
NSLog(@"this stuck is done!");//end viewDidLoad.
-(BOOL)countSampleTest: (NSMutableArray *)localArr serverArr:(NSMutableArray *)tmpServerArr sampleTest:(NSArray *)sampleTest{
BOOL tf;
int cntSampleLoc = 0;
int cntSampleServer = 0;
for (int i = 0 ; i < [sampleTest count]; i++) {
NSCountedSet * localCountedSet = [[ NSCountedSet alloc] initWithArray:localArr];
NSCountedSet * serverCountedSet = [[ NSCountedSet alloc] initWithArray:tmpServerArr];
cntSampleLoc += [localCountedSet countForObject:sampleTest[i]];
//if (localArr[i] in tmpServerArr ) {
cntSampleServer +=[serverCountedSet countForObject:sampleTest[i]];
// }
}
if (cntSampleServer == cntSampleLoc) {
tf= true;
}else tf = false;
return tf;}
答案 0 :(得分:2)
我想到的第一个解决方案非常简单:
NSArray *serverArray;
NSMutableArray *localArray;
// This will give you the difference.
[localArray removeObjectsInArray:serverArray];
Docs说:
removeObjectsInArray:
此方法类似于
removeObject:
,但它 允许您有效使用单个删除大量对象 操作
答案 1 :(得分:1)
您还可以{@ 1}}和NSSet
,这对于大型数据集来说会更快:
NSMutableSet
另请参阅this SO question,详细了解NSMutableSet *serverSet = [NSMutableSet setWithArray: serverArray];
NSSet *localSet = [NSSet setWithArray: localArray];
[serverSet minusSet: localSet];
NSArray *deletedObjects = [serverSet allObjects];
与NSArray
之间的效果差异。
答案 2 :(得分:0)
无需编写算法:
保持数组排序会有所帮助。
想象一下在字典中寻找“鼠标”这个词。如果你从“a”开始,只是检查每个单词是否是“鼠标”,它将永远带你。但是知道“m”字会出现在中间位置,并且“o”位于“m”的中间位置意味着你可以更快地找到你的单词。
在一次采访中,这有一个额外的好处,就是表明你知道如何在问题范围之外思考并让你有机会展示你所知道的其他事情。< / p>
答案 3 :(得分:0)
O(N + N + N)= O(3N)= 0(N)