ios - reconocedor - La forma más rápida de verificar si una matriz contiene los mismos objetos de otra matriz
detectar objetos camara android (10)
El objetivo es comparar dos matrices y comprobar si contienen los mismos objetos (lo más rápido posible; hay muchos objetos en las matrices). Las matrices no se pueden comprobar con isEqual:
ya que están ordenadas de forma diferente.
Ya probé la solución publicada aquí ( https://stackoverflow.com/a/1138417 - vea el último fragmento de código de la publicación de Peter Hosey). Pero esto no funciona con matrices ordenadas de manera diferente.
El código que estoy usando ahora es el siguiente:
+ (BOOL)arraysContainSameObjects:(NSArray *)array1 andOtherArray:(NSArray *)array2 {
// quit if array count is different
if ([array1 count] != [array2 count]) return NO;
BOOL bothArraysContainTheSameObjects = YES;
for (id objectInArray1 in array1) {
BOOL objectFoundInArray2 = NO;
for (id objectInArray2 in array2) {
if ([objectInArray1 isEqual:objectInArray2]) {
objectFoundInArray2 = YES;
break;
}
}
if (!objectFoundInArray2) {
bothArraysContainTheSameObjects = NO;
break;
}
}
return bothArraysContainTheSameObjects;
}
Esto funciona, pero esas son dos enumeraciones rápidas anidadas. ¿Hay alguna manera de hacer una comparación más rápida?
¿Qué hay de convertir ambas matrices en conjuntos y compararlos.
NSSet *set1 = [NSSet setWithArray:arr1];
NSSet *set2 = [NSSet setWithArray:arr2];
Compara los dos usando
if([set1 isEqualToSet:set2]) {
}
De esta manera, la complejidad es O (N ^ 2), si sigue este enfoque no puede hacerlo con una complejidad menor. Mientras que en su lugar, puede hacerlo con O (N log (N)) si ordena ambas matrices y luego las compara. De esta manera, después de ordenarlos, lo hará utilizando isEqualToArray: en otras N operaciones.
Intenté que la respuesta aceptada funcionara, pero no era la mejor opción para mi situación.
Encontré esta respuesta y todo el crédito va a @joel kravets por el método.
Básicamente, la clasificación mediante un comparador le permite ordenar los objetos con mayor facilidad, de ahí el problema al que me enfrenté al intentar usar la solución anterior.
NSArray * array1 = [NSArray arrayWithArray:users];
NSArray * array2 = [NSArray arrayWithArray:threadUsers];
id mySort = ^(BUser * user1, BUser * user2){
return [user1.name compare:user2.name];
};
array1 = [array1 sortedArrayUsingComparator:mySort];
array2 = [array2 sortedArrayUsingComparator:mySort];
if ([array1 isEqualToArray:array2]) {
NSLog(@"both are same");
}
else{
NSLog(@"both are different");
}
Anteriormente, había intentado usar otras respuestas como las anteriores, usando break para recorrer los bucles, pero al final esta respuesta fue la más fácil, probablemente debido a su velocidad y también que al final tenemos la instrucción if que nos permite poner código dependiendo de Si son iguales o diferentes.
Gracias a Anoop por guiarme en el camino correcto ya Joel por ayudarme a mejorar su eficiencia.
Sé que es tarde pero solo quiero compartir lo que hice ..
NSString *stringArr1 = [NSString stringWithFormat:@"%@", array1];
NSString *stringArr2 = [NSString stringWithFormat:@"%@", array2];
if ([stringArr1 isEqual: stringArr2])
NSLog(@"identical");
else
NSLog(@"not");
esto es como comparar "@ [@ 1, @ 2, @ 3, @ 4]" == "[@ 3, @ 2, @ 1, @ 4]" .. lo que obviamente es falso ..
Según su código, usted es estricto con el mismo número de elementos y cada objeto de la primera matriz debe estar allí en la segunda matriz y viceversa.
La forma más rápida sería ordenar la matriz y compararlos.
Ex:
NSArray *array1=@[@"a",@"b",@"c"];
NSArray *array2=@[@"c",@"b",@"a"];
array1=[array1 sortedArrayUsingSelector:@selector(compare:)];
array2=[array2 sortedArrayUsingSelector:@selector(compare:)];
if ([array1 isEqualToArray:array2]) {
NSLog(@"both have same elements");
}
else{
NSLog(@"both having different elements");
}
Si desea comprobar si ambas matrices contienen los mismos duplicados, simplemente use NSCountedSet. Es como un NSSet, pero cada objeto del conjunto también tiene un recuento que le indica la frecuencia con la que se ha agregado. Asi que
BOOL same = (array1.count == array2.count);
if (same && array.count > 0)
{
NSCountedSet* set1 = [[NSCountedSet alloc] initWithArray:array1];
NSCountedSet* set2 = [[NSCountedSet alloc] initWithArray:array2];
same = ([set1 isEqual: set2]);
}
No importa cómo lo haga, esto llevará mucho tiempo, por lo que puede considerar si hay casos especiales que se puedan manejar más rápido. ¿Son estos arreglos generalmente iguales, o casi iguales, o es cierto el 99% del tiempo que son diferentes y que el 99% del tiempo un elemento aleatorio de array1 no está en array2? ¿Las matrices se ordenan a menudo? En ese caso, puede verificar si hay objetos idénticos en posiciones idénticas y luego considerar solo los objetos que no son iguales. Si una matriz contiene los objetos a, b, c, d, ey la otra contiene a, b, x, d, y, entonces solo necesita comparar la matriz [c, e] contra [x, y].
Supongo que esto hará:
[array1 isEqualToArray:array2];
devuelve bool;
Utilice el método includesObject: en lugar de iterar toda la matriz.
NSArray *array;
array = [NSArray arrayWithObjects: @"Nicola", @"Margherita", @"Luciano", @"Silvia", nil];
if ([array containsObject: @"Nicola"]) // YES
{
// Do something
}
Me gusta esto
+ (BOOL)arraysContainSameObjects:(NSArray *)array1 andOtherArray:(NSArray *)array2 {
// quit if array count is different
if ([array1 count] != [array2 count]) return NO;
BOOL bothArraysContainTheSameObjects = YES;
for (id objectInArray1 in array1) {
if (![array2 containsObject:objectInArray1])
{
bothArraysContainTheSameObjects = NO;
break;
}
}
return bothArraysContainTheSameObjects;
}
[docTypes containsObject:@"Object"];
Funcionará para su req. Tan pronto como rápido le devolverá un valor booleano.
NSArray *filtered = [someArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"someParamter == %@", paramValue]]];
if (filtered.count) {
}
La ventaja principal es que puede usarlo para cualquier tipo de objetos: personalizado, sistema, NSDictionary. por ejemplo, necesito saber si mi pila de UINavigationController contiene MySearchResultsVC y MyTopMenuItemsVC o no:
NSArray *filtered = [self.navigationController.viewControllers filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:@"class IN %@",
[NSArray arrayWithObjects:
[MySearchResultsVC class],
[MyTopMenuItemsVC class],
nil]]];
if (filtered) {
/* ok, now we can handle it! */
}