Estoy buscando el idioma estándar para iterar sobre un NSArray. Mi código debe ser adecuado para OS X 10.4+.
fuente
Estoy buscando el idioma estándar para iterar sobre un NSArray. Mi código debe ser adecuado para OS X 10.4+.
El código generalmente preferido para 10.5 + / iOS.
for (id object in array) {
// do something with object
}
Esta construcción se utiliza para enumerar objetos en una colección que se ajusta al NSFastEnumeration
protocolo. Este enfoque tiene una ventaja de velocidad porque almacena punteros a varios objetos (obtenidos mediante una sola llamada a un método) en un búfer y los itera avanzando a través del búfer utilizando la aritmética del puntero. Esto es mucho más rápido que llamar -objectAtIndex:
cada vez a través del ciclo.
También vale la pena señalar que, si bien técnicamente puede usar un bucle for-in para recorrer un paso NSEnumerator
, he descubierto que esto anula prácticamente todas las ventajas de velocidad de la enumeración rápida. La razón es que la NSEnumerator
implementación predeterminada de -countByEnumeratingWithState:objects:count:
coloca solo un objeto en el búfer en cada llamada.
radar://6296108
Informé esto en (La enumeración rápida de NSEnumerators es lenta) pero se devolvió como No se debe corregir. La razón es que la enumeración rápida busca previamente un grupo de objetos, y si desea enumerar solo en un punto dado en el enumerador (por ejemplo, hasta que se encuentre un objeto en particular o se cumpla una condición) y use el mismo enumerador después de dividir del bucle, a menudo sería el caso de que se omitieran varios objetos.
Si está codificando para OS X 10.6 / iOS 4.0 y superior, también tiene la opción de usar API basadas en bloques para enumerar matrices y otras colecciones:
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
// do something with object
}];
También puede usar -enumerateObjectsWithOptions:usingBlock:
y pasar NSEnumerationConcurrent
y / o NSEnumerationReverse
como argumento de opciones.
El idioma estándar para pre-10.5 es usar un NSEnumerator
bucle while y un while, así:
NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
// do something with object
}
Recomiendo que sea simple. Atarse a un tipo de matriz es inflexible, y el supuesto aumento de velocidad de uso -objectAtIndex:
es insignificante para la mejora con una enumeración rápida en 10.5+ de todos modos. (La enumeración rápida en realidad usa la aritmética de puntero en la estructura de datos subyacente, y elimina la mayor parte de la sobrecarga de llamadas al método). La optimización prematura nunca es una buena idea: resulta en un código más desordenado para resolver un problema que de todos modos no es su cuello de botella.
Al usarlo -objectEnumerator
, puede cambiar fácilmente a otra colección enumerable (como an NSSet
, keys in an NSDictionary
, etc.), o incluso cambiar -reverseObjectEnumerator
a enumerar una matriz al revés, todo sin otros cambios de código. Si el código de iteración está en un método, incluso podría pasar cualquiera NSEnumerator
y el código ni siquiera tiene que preocuparse por lo que está iterando. Además, un NSEnumerator
(al menos los proporcionados por el código de Apple) retiene la colección que está enumerando siempre que haya más objetos, por lo que no tiene que preocuparse por cuánto tiempo existirá un objeto lanzado automáticamente.
Quizás lo más importante de lo que una NSEnumerator
(o enumeración rápida) lo protege es tener un cambio de colección mutable (matriz o de otro tipo) debajo de usted sin su conocimiento mientras lo enumera. Si accede a los objetos por índice, puede encontrarse con extrañas excepciones o errores ocasionales (a menudo mucho después de que se haya producido el problema) que pueden ser terribles de depurar. La enumeración que usa uno de los modismos estándar tiene un comportamiento de "falla rápida", por lo que el problema (causado por un código incorrecto) se manifestará de inmediato cuando intente acceder al siguiente objeto después de que se haya producido la mutación. A medida que los programas se vuelven más complejos y multiproceso, o incluso dependen de algo que el código de terceros puede modificar, el código de enumeración frágil se vuelve cada vez más problemático. Encapsulación y abstracción FTW! :-)
for (id object in array)
, ¿hay alguna manera de determinar también el índice actual de los objetos en la matriz, o necesita un contador separado?for
bucle como este:for(;;) { id object = [ e nextObject ] ; if ( !e ) { break ; } ... your loop operation ... }
Para OS X 10.4.xy versiones anteriores:
Para OS X 10.5.x (o iPhone) y más allá:
fuente
for (NSUInteger i = 0, count = [myArray count]; i < count; i++)
es probablemente el más eficiente y conciso que obtendrá para este enfoque.Los resultados de la prueba y el código fuente están a continuación (puede establecer el número de iteraciones en la aplicación). El tiempo es en milisegundos, y cada entrada es un resultado promedio de ejecutar la prueba 5-10 veces. Descubrí que, en general, tiene una precisión de 2-3 dígitos significativos y después de eso variaría con cada ejecución. Eso da un margen de error de menos del 1%. La prueba se ejecutaba en un iPhone 3G, ya que esa era la plataforma de destino que me interesaba.
Las clases proporcionadas por Cocoa para manejar conjuntos de datos (NSDictionary, NSArray, NSSet, etc.) proporcionan una interfaz muy agradable para administrar la información, sin tener que preocuparse por la burocracia de la administración de la memoria, la reasignación, etc. Sin embargo, esto tiene un costo. . Creo que es bastante obvio que decir que usar un NSArray of NSNumbers será más lento que un C Array de flotantes para iteraciones simples, así que decidí hacer algunas pruebas, ¡y los resultados fueron bastante impactantes! No esperaba que fuera tan malo. Nota: estas pruebas se realizan en un iPhone 3G, ya que esa es la plataforma de destino que me interesaba.
En esta prueba, hago una comparación de rendimiento de acceso aleatorio muy simple entre un flotante C * y NSArray of NSNumbers
Creo un bucle simple para resumir el contenido de cada matriz y cronometrarlos usando mach_absolute_time (). ¡El NSMutableArray tarda en promedio 400 veces más! (¡no 400 por ciento, solo 400 veces más! ¡eso es 40,000% más!).
Encabezamiento:
// Array_Speed_TestViewController.h
// Prueba de velocidad de matriz
// Creado por Mehmet Akten el 05/02/2009.
// Copyright MSA Visuals Ltd. 2009. Todos los derechos reservados.
Implementación:
// Array_Speed_TestViewController.m
// Prueba de velocidad de matriz
// Creado por Mehmet Akten el 05/02/2009.
// Copyright MSA Visuals Ltd. 2009. Todos los derechos reservados.
De: memo.tv
////////////////////
Disponible desde la introducción de bloques, esto permite iterar una matriz con bloques. Su sintaxis no es tan buena como la enumeración rápida, pero hay una característica muy interesante: la enumeración concurrente. Si el orden de enumeración no es importante y los trabajos se pueden realizar en paralelo sin bloqueo, esto puede proporcionar una aceleración considerable en un sistema de múltiples núcleos. Más sobre eso en la sección de enumeración concurrente.
/////////// NSFastEnumerator
La idea detrás de la enumeración rápida es utilizar el acceso rápido a la matriz C para optimizar la iteración. No solo se supone que es más rápido que el NSEnumerator tradicional, sino que Objective-C 2.0 también proporciona una sintaxis muy concisa.
/////////////////
NSEnumerator
Esta es una forma de iteración externa: [myArray objectEnumerator] devuelve un objeto. Este objeto tiene un método nextObject que podemos llamar en un bucle hasta que devuelva nil
/////////////////
objectAtIndex: enumeración
Usar un bucle for que aumenta un número entero y consultar el objeto usando [myArray objectAtIndex: index] es la forma más básica de enumeración.
////////////// De: darkdust.net
fuente
Las tres formas son:
fuente
Agregue
each
método en suNSArray category
, lo necesitará muchoCódigo tomado de ObjectiveSugar
fuente
Así es como declaras una serie de cadenas e iteras sobre ellas:
fuente
Para Swift
fuente
Hacer esto :-
fuente