Skip to content

Instantly share code, notes, and snippets.

@vstarck
Created June 25, 2011 15:54
Show Gist options
  • Save vstarck/1046611 to your computer and use it in GitHub Desktop.
Save vstarck/1046611 to your computer and use it in GitHub Desktop.
Implementacion de iteraciones basicas y metodos auxiliares
/**
* Constructor que provee de la funcionalidad
* de iteracion
*
* @constructor
*/
function Iterable() {}
/**
* Excepcion utilizada para detener la iteracion
*/
Iterable.StopException = function() {};
/**
* Itera los elementos provistos por el sujeto
*
* @param {Function} iterator
* @param {Object} context
* @return {Object} el sujeto
*/
Iterable.prototype.each = function(iterator, context) {
if(typeof this._next != 'function')
throw new Error('Unimplemented method: _next');
try {
iterator.call(context, this._next());
return this.each(iterator, context);
} catch(e) {
if(e instanceof Iterable.StopException)
return this
throw e;
}
if(typeof this._reset == 'function')
this._reset();
return this;
};
/**
* Reduce el input multiple a un unico valor
* a partir del valor inicial
*
* @param {Function} iterator
* @param {Object} memo
* @param {Object} context
* @return {Object}
*/
Iterable.prototype.reduce = function(iterator, memo, context) {
this.each(function(e) {
memo = iterator.call(context, memo, e);
});
return memo;
};
/**
* Devuelve el length calculado
*
* @return {Number}
*/
Iterable.prototype.size = function() {
return this.reduce(function(memo, e) {
return memo + 1;
}, 0);
};
/**
* Devuelve un array con la transformacion de
* cada elemento
*
* @param {Function} iterator
* @param {Object} context
* @return {Array}
*/
Iterable.prototype.map = function(iterator, context) {
var res = [];
this.each(function(e) {
res.push(
iterator.call(context, e)
);
});
return res;
};
Iterable.prototype.pluck = function(property) {
return this.map(function(e) {
return e[property];
});
};
/**
* Devuelve los elementos que pasen como ciertos
* para el iterador
*
* @return {Array}
*/
Iterable.prototype.filter = function(iterator, context) {
var res = [];
this.each(function(e) {
if(iterator.call(context, e)) {
res.push(e);
}
});
return res;
};
/**
* Filtra los elementos que pasen como ciertos
* para el iterador
*
* @return {Array}
*/
Iterable.prototype.reject = function(iterator, context) {
return this.filter(function(e) {
return !iterator.call(context, e);
});
};
Iterable.prototype.uniq = function() {
var res = [];
this.each(function(e) {
if(res.indexOf(e) == -1) {
res.push(e);
}
});
return res;
};
/**
* Verifica si todos los elementos pasan como ciertos
* para el iterador
*
* @param {Function} iterator
* @param {Object} context
* @return {Boolean}
*/
Iterable.prototype.all = function(iterator, context) {
var status = true;
this.each(function(e) {
// Si hay un falso, detenemos la iteracion
if(!iterator.call(context, e)) {
status = false;
throw new Iterable.StopException;
}
});
return status;
};
/**
* Verifica si al menos un elemento cumple con la condicion
*
* @param {Function} iterator
* @param {Object} context
* @return {Boolean}
*/
Iterable.prototype.any = function(iterator, context) {
var status = false;
this.each(function(e) {
// Si hay un true, detenemos la iteracion
if(!iterator.call(context, e)) {
status = true;
throw new Iterable.StopException;
}
});
return status;
};
/**
* Deuvelve el primer elemento que cumpla la condicion
*
* @param {Function} iterator
* @param {Object} context
* @return {Boolean}
*/
Iterable.prototype.detect = function(iterator, context) {
var el = null;
this.each(function(e) {
// Si hay un true, detenemos la iteracion
if(iterator.call(context, e)) {
el = e;
throw new Iterable.StopException;
}
});
return el;
};
// ----------------
/**
* Genera un rango numerico iterable
*
* @param {Number} from
* @param {Number} to
* @constructor
*/
function Range (from, to) {
this.actual = this.from = from;
this.to = to;
}
// Extendemos el constructor iterador
Range.prototype = new Iterable();
/**
* Implementacion del metodo requerido por Iterator
*
* @return {Number}
*/
Range.prototype._next = function() {
// Limitamos la ejecucion a los numeros que
// pertenezcan al rango
if(this.actual > this.to)
throw new Iterable.StopException;
// Devolvemos el indice actual
return this.actual++;
};
/**
* Implementacion del metodo
*/
Range.prototype._reset = function() {
this.actual = this.from;
};
//----------------------------------------------------
console.log(
'Obtenemos la sumatoria del rango [0, 10]',
(new Range(0, 10)).reduce(function(memo, e) {
return memo + e;
}, 0)
);
console.log(
'Obtenemos el tamaño',
(new Range(0, 10)).size()
);
console.log(
'Obtenemos los cuadrados',
(new Range(0, 10)).map(function(e) {
return e * e;
})
);
console.log(
'Verificamos si todos los elementos son pares',
(new Range(0, 10)).all(function(e) {
return e % 2 != 0;
})
);
console.log(
'Verificamos si al menos un elemento par',
(new Range(0, 10)).any(function(e) {
return e % 2 != 0;
})
);
console.log(
'Obtenemos el primer elemento divisible por 3 y por 2',
(new Range(0, 10)).detect(function(e) {
return e % 2 != 0 && e % 3 != 0;
})
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment