objective array ios objective-c nsarray

ios - objective - NSArray encontrar objeto u objetos-mejores prácticas



nsdictionary objective c (5)

Me intrigó el comentario de rmaddys, así que he comprobado la diferencia entre bucle y predicado.

Asumamos un objeto simple con la propiedad NSString. Lo he insertado en la matriz 10 000 veces, cada vez con un valor de propiedad diferente.

En el peor de los casos, cuando el objeto deseado estaba en la última posición de la matriz, el enfoque de bucle fue 3.5x más rápido que NSPredicate (0.39s vs 0.11s, arraySize = 10000, 10 iteraciones, iPad Mini)

Código que utilicé para referencia: pastebin

Solución: He marcado la respuesta de @ BlackRider como correcta, ya que es la más versátil, especialmente para comparaciones complejas, sin embargo, hay otras respuestas y comentarios muy buenos. Le recomendaría a cualquier persona que tenga la misma pregunta o una similar que los revise y evalúe el mejor curso de acción para su situación específica.

En mi situación, en realidad no estoy usando la solución BlackRider en mi implementación. He elegido usar mi propia solución (ver Edición # 2 a continuación) con la ayuda de los comentarios de @ JoshCaswell y la sugerencia de @ voromax de indexesOfObjectsWithOptions:passingTest: debido al hecho de que mis comparaciones son muy simples en esta situación.

Gracias a todos los que respondieron y aportaron ideas.

Estoy buscando una forma eficiente de recuperar un objeto de un NSArray basado en una propiedad de ese objeto (un identificador único, en este caso). En C # .NET usando Linq haría algo como

MyObject obj = myList.Single(o => o.uuid == myUUID);

También me pregunto si hay una manera eficiente de obtener una matriz de objetos que coincida con una propiedad no única. De nuevo, con Linq se vería como

List<MyObject> objs = myList.Where(o => o.flag == true).ToList();

Por supuesto, puedo escribir bucles para hacer esto, pero no serían reutilizables y desconfío de su rendimiento.

Encontrar un objeto con una ID única:

-(MyObject*)findObjectWithUUID:(NSString*)searchUUID{ for (MyObject* obj in _myArray){ if([obj.uuid isEqualToString: searchUUID]) return obj; } }

Encontrar una matriz de objetos:

-(NSArray*)findObjectsWithFlag:(BOOL)f{ NSMutableArray* arr = [NSMutableArray array]; for (MyObject* obj in _myArray){ if(obj.flag == f) [arr addObject:obj]; } return arr; }

- EDITAR -

Por suerte, en la primera situación, el objeto que busco tiene un identificador único y sé que solo habrá uno. Se me ocurrió una solución para implementar isEqual en mi objeto que será invocado por indexOfObject:

- (BOOL)isEqual:(id)object{ return [self.uuid isEqualToString: ((MyObject*)object).uuid]; }

Y luego crea un objeto de búsqueda "falso" y úsalo para encontrar el verdadero

MyObject *lookupObject = [[MyObject alloc] init]; lookupObject.uuid = searchUUID; MyObject *actualObject = [_myArray objectAtIndex:[_myArray indexOfObject:lookupObject]];

Este es esencialmente el mismo que el bucle for-in que publiqué anteriormente, pero podría ser más legible y más reutilizable. Por supuesto, esto solo funciona para encontrar un objeto único y no aborda la segunda parte de mi pregunta.

- EDIT 2 -

Verificación de Class e implementación de hash como se recomienda en los comentarios.

- (BOOL)isEqual:(id)object{ return [object isKindOfClass:[MyObject class]] && [self.uuid isEqualToString: ((MyObject*)object).uuid]; } - (NSUInteger)hash{ return [self.uuid hash]; }


Puede usar [NSPredicate] , que le proporciona una sintaxis similar a una consulta para la búsqueda. Echa un vistazo a esta página para la descripción de la sintaxis del predicado. Aquí hay un ejemplo simple:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"propertyName == %@", @"value"]; NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];

En cuanto al rendimiento, creo que su solución está bien, ya que cualquier búsqueda en una matriz debe recorrer todos los elementos de todos modos, y luego, para cada objeto, comparar el valor de un campo con el valor que busca. Puede optimizar las búsquedas repetidas dentro de los mismos datos, por ejemplo, creando y rellenando un diccionario que asigna valores de algún campo a los objetos coincidentes (o colecciones de objetos, si la asignación es de uno a muchos).


Sé que está relacionado con NSArray pero si lo hacemos utilizando Swift y utilizando el Swift Array, que es una struct , será mucho más fácil.

Swift 2.2 / Swift 3.0 / Swift 4.x Funciona bien en todas las versiones

Asumamos que tenemos una clase de modelo personalizado

class User { var userId = 0 var userName = "" }

Y supongamos que tenemos una matriz nombrada como usersArray que tiene objetos personalizados de User clase User .

Y queremos obtener un objeto de esta matriz con userId = 100 por ejemplo:

let filteredArray = usersArray.filter({$0.userId == 100})

Esta matriz filtrada contendrá todos los objetos personalizados que tienen userId como 100

print(filteredArray[0].userName) //will print the name of the user with userId = 100



solo para aquellos que están interesados, he encontrado que la forma más rápida de buscar a través de NSArray es mediante el uso de un bucle for en un hilo de fondo. utilizando el método [self performSelectorInBackground ...]. En un NSArray de 10000 objetos personalizados, realicé una búsqueda exhaustiva en aproximadamente 1 segundo. En el hilo principal tardó alrededor de 10 segundos o más.