IteradorEn programación de computadoras, un iterador se refiere al objeto que permite al programador recorrer un contenedor, (una colección de elementos) particularmente listas.[1] [2] [3] Varios tipos de iteradores se suministran frecuentemente a través de una interfaz del contenedor. La interfaz y la semántica de un determinado iterador suelen ser fijas. Un iterador sigue una ruta y da acceso a elementos de datos del contenedor, pero no realiza iteración (es decir, no tiene total libertad, como sugiere su terminología). Un iterador se comporta como el cursor de una base de datos. Los iteradores se empezaron a utilizar en el lenguaje de programación CLU en 1974. DescripciónIteradores externos y un patrón iteradorUn iterador externo puede ser imaginado como un tipo de puntero que tiene dos operaciones primarias: referenciar un elemento particular en la colección de objetos y modificarse para apuntar al siguiente elemento. También debe existir una manera de crear un iterador para apuntar a algún primer elemento así como alguna manera de determinar cuando el iterador ha agotado todos los elementos en el contenedor. Dependiendo del lenguaje y del uso deseado, los iteradores también pueden proporcionar operaciones adicionales o mostrar comportamientos diferentes. El propósito primario de un iterador es permitir que un usuario procese cada elemento de un contenedor mientras aísla al usuario de la estructura interna de un contenedor. Esto permite que el contenedor almacene elementos de la manera que él desee permitiendo que el usuario trate como si fuera una simple lista o secuencia. Una clase iterador normalmente se proyecta en estrecha coordinación con la clase contenedor correspondiente. Normalmente, el contenedor proporciona los métodos para crear iteradores. GeneradoresUna manera de implementar iteradores es utilizar un tipo especial de su subrutina, conocido como un generador, que puede producir valores para quien lo llama varias veces (en lugar de devolver sólo uno). A continuación se puede ver un ejemplo de un generador que devuelve los números de Fibonacci mediante la declaración siguiente código (en Python): def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
for numero in fibonacci(): # Utilización de generador como iterador
print(numero)
Iteradores implícitosAlgunos lenguajes orientados a objetos como C#, Delphi (versiones más recientes), Go (lenguaje de programación), Java , Lua, Perl, Python, Ruby, ofrecen una manera intrínseca de iteración a través de elementos de un objeto contenedor sin la introducción de un objeto iterador explícito. Un objeto iterador real puede existir en realidad, pero si existe, no se expone dentro del código fuente del lenguaje. Los iteradores implícitos se manifiestan generalmente por una declaración "foreach" (u otra equivalente), como en el siguiente ejemplo en Python: for valor in iterable:
print(valor)
Otras veces pueden ser creados por un objeto de la colección, como en este ejemplo en Ruby: iterable.each do |valor|
puts valor
end
Este estilo de iteración es llamado a veces "iteración interna" debido a que su código se ejecuta completamente dentro del contexto del objeto iterable (que controla todos los aspectos de la iteración) y el programador sólo proporciona la operación para ejecutar en cada paso (utilizando una función anónima). Los lenguajes que soportan comprensión de lista o construcciones similares también pueden hacer uso de iteradores implícitos durante la construcción de la lista de resultados, como en Python: nombres = [persona.nombre for persona in lista if persona.femenino]
A veces la naturaleza oculta implícita es sólo parcial. El lenguaje C++ tiene pocas plantillas de función, como En diferentes lenguajes de programaciónJavaComo un patrón para recorrer listas, conjuntos, mapas, etc: Es lo que usted llamaría "cursor" si escribiera procedimientos almacenados en SQL. Por lo tanto, no es un concepto nuevo o extraordinariamente difícil de manipular. Si se sabe que la List es un ArrayList, entonces no hay problemas en el uso del índice en vez de utilizar un Iterator. Para todos los demás tipos (LinkedList, Set, Map, etc.) hay que usar el Iterator. Y de todos modos se continúa usando el for: // digamos que la colección sea una colección BlaBleBli
for (Iterator it = coleccion.iterator() it.hasNext()) {
BlaBleBli obj = (BlaBleBli) it.next();
}
En Java 5, el iterador puede incluso esconderse: for (BlaBleBli obj: coleccion) {
En el siguiente ejemplo tenemos la clase principal MenuItem que simplemente es un ítem de un menú que tiene un nombre, este podría ser un menú que aparecería en la sección de menú de un sitio, por ejemplo: class MenuItem {
String nombre;
MenuItem(String nombre) {
this.nombre = nombre;
}
}
interface Iterator {
boolean hasNext();
Object next();
}
public class MenuIterator implements Iterator {
MenuItem[] items;
int posicion = 0;
public MenuIterator(MenuItem[] items) {
this.items = items;
}
public Object next() {
MenuItem menuItem = items[posicion];
posicion++;
return menuItem;
}
public boolean hasNext() {
if (posicion >= items.length || items[posicion] == null) {
return false;
}
return true;
}
}
PythonLos iteradores en Python son una parte fundamental del lenguaje y en muchos casos pasan desapercibidos, pues se utilizan implícitamente en la declaración for valor in secuencia:
print(valor)
Los diccionarios de Python (una forma de matriz asociativa) también pueden ser iterados directamente, cuando se devuelven las claves del diccionario; o el método items de un diccionario puede ser iterado sobre donde produce pares clave, valores correspondientes como una tupla: for clave in diccionario:
valor = diccionario[clave]
print(clave, valor)
for clave, valor in diccionario.items():
print(clave, valor)
Los iteradores, sin embargo, se pueden utilizar y definir explícitamente. Para cualquier tipo de secuencia iterable o clase, la función nativa it = iter(secuencia)
while True:
try:
valor = it.next() # en Python 2.x
valor = next(it) # en Python 3.x
except StopIteration:
break
it = iter(it)
print(valor)
Cualquier clase definida por el usuario puede soportar iteración estándar (implícita o explícita), mediante la definición de un método Los generadores de Python implementan este protocolo de iteración. PHPEl foreach fue introducido en la versión 4.0 de PHP y hecho compatible con los objetos como valores en 4.0 Beta 4. Sin embargo, el soporte a iteradores se añadió en PHP 5 a través de la introducción de la interfaz interna atravesable (no implementable en el código PHP, sino en lenguaje C. Las dos interfaces principales para la implementación de código PHP que permiten que los objetos sean iterados a través del bucle foreach son Iterator y IteratorAggregate. Este último no requiere que la clase de implementación declare todos los métodos requeridos, sino que implementa un método a para acceder (getter) ( La implementación más simple es envolviendo un arreglo, esto puede ser útil para sugerencia de tipo y ocultación de información. namespace Wikipedia\Iterator;
final class ArrayIterator extends \Iterator {
private $array;
public function __construct(array $array) {
$this->array = $array;
}
public function rewind() {
echo 'rebobinado' , PHP_EOL;
reset($this->array);
}
public function current() {
$value = current($this->array);
echo "actual: {$value}" , PHP_EOL;
return $value;
}
public function key() {
$key = key($this->array);
echo "clave: {$key}" , PHP_EOL;
return $key;
}
public function next() {
$value = next($this->array);
echo "siguiente: {$value}" , PHP_EOL;
return $value;
}
public function valid() {
$valid = $this->current() !== false;
echo 'validar: ' , ($valid ? 'true' : 'false') , PHP_EOL;
return $valid;
}
}
Todos los métodos de la clase de ejemplo se utilizan durante la ejecución de un bucle foreach completo (
El siguiente ejemplo ilustra una clase PHP que implementa la interfaz Traversable, que podría ser envuelta en una clase IteratorIterator para actuar sobre los datos antes de ser devuelta al bucle foreach. El uso junto con la constante mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli('host.example.com', 'username', 'password', 'database_name');
// La clase \mysqli_result retornada por el metodo implementa la interfaz interna ''Traversable''.
foreach ($mysqli->query('SELECT `a`, `b`, `c` FROM `table`', MYSQLI_USE_RESULT) as $row) {
//Actúa en la fila devuelta, que es un arreglo asociativo.
}
Véase tambiénReferencias
|