Foros del Web » Programando para Internet » Javascript »

No repetir, Array mostrado al Azar

Estas en el tema de No repetir, Array mostrado al Azar en el foro de Javascript en Foros del Web. Hola :D, lo intenté hacerlo con if() pero viendo que escoge al azar y no es una rotación no puedo tener el valor de la ...
  #1 (permalink)  
Antiguo 05/02/2011, 12:27
Avatar de raxper  
Fecha de Ingreso: enero-2010
Ubicación: ------
Mensajes: 472
Antigüedad: 14 años, 10 meses
Puntos: 2
No repetir, Array mostrado al Azar

Hola :D, lo intenté hacerlo con if() pero viendo que escoge al azar y no es una rotación no puedo tener el valor de la variable. for?

Código Javascript:
Ver original
  1. var forosdelweb = new Array(3)
  2. forosdelweb[0] = "Uno";
  3. forosdelweb[1] = "Dos";
  4. forosdelweb[2] = "Tres";
  5.  
  6. document.write("<a onclick='alert(forosdelweb[Math.round(Math.random()*2)])'>Alert que no se repita</a>")
__________________
/^sleep:\/\//;
  #2 (permalink)  
Antiguo 05/02/2011, 16:40
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 5 meses
Puntos: 310
Respuesta: No repetir, Array mostrado al Azar

Mira a ver si funciona esto:
Código Javascript:
Ver original
  1. var fdw = ['uno', 'dos', 'tres'], arr = fdw;
  2. function noRepetir(list){
  3.  var num = Math.floor(Math.random()*list.length), str = arr[num];
  4.  arr = arr.length ? arr : list;
  5.  arr.splice(num, 1);
  6.  return str;
  7. }
Saludos (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #3 (permalink)  
Antiguo 05/02/2011, 17:56
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años, 7 meses
Puntos: 1485
Respuesta: No repetir, Array mostrado al Azar

buenas...

@cronos, que tal! estaba observando el codigo y entiendo la idea que tienes: restaurar el array por el original cuando se vacia. lo cierto es que no ocurre asi puesto que los tipos de datos complejos se pasan como referencia y no copia. es decir, arr es una referencia de fdw. para hacer una copia de un array puedes utilizar cualquier funcion que devuelva un nuevo array, el mas apropiado concat.
Código:
var a = [true, 'string', 0], b = a.concat(); // crear array y copiar ;
a.shift(); // eliminar un elemento de un array ;
alert("a: "+ a +"\nb: "+ b);
__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.
  #4 (permalink)  
Antiguo 05/02/2011, 20:23
Avatar de buzu  
Fecha de Ingreso: octubre-2006
Ubicación: San Francisco, CA
Mensajes: 2.168
Antigüedad: 18 años, 1 mes
Puntos: 122
Respuesta: No repetir, Array mostrado al Azar

lo mismo lo puedes hacer con un loop, pero si lo menciono es solo para evitar que lo hagas así. Creo que el método de zerokilled es mejor ya que no depende de la longitud del array como en el caso del loop.
__________________
twitter: @imbuzu
  #5 (permalink)  
Antiguo 06/02/2011, 07:36
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 5 meses
Puntos: 310
Respuesta: No repetir, Array mostrado al Azar

Cita:
Iniciado por zerokilled Ver Mensaje
buenas...

@cronos, que tal! estaba observando el codigo y entiendo la idea que tienes: restaurar el array por el original cuando se vacia. lo cierto es que no ocurre asi puesto que los tipos de datos complejos se pasan como referencia y no copia. es decir, arr es una referencia de fdw. para hacer una copia de un array puedes utilizar cualquier funcion que devuelva un nuevo array, el mas apropiado concat.
Código:
var a = [true, 'string', 0], b = a.concat(); // crear array y copiar ;
a.shift(); // eliminar un elemento de un array ;
alert("a: "+ a +"\nb: "+ b);
Hola ZK!
No sabía eso! O.O ¿Qué sugieres entonces? Tengo esto pero no funciona:
Código Javascript:
Ver original
  1. var fdw = ['uno', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete'], arr = fdw;
  2. function noRepetir(list){
  3.  arr = arr.length ? arr : list.concat();
  4.  var num = Math.floor(Math.random()*arr.length), str = arr[num];
  5.  arr.splice(num, 1);
  6.  return str;
  7. }
  8. for(i=0; i<14; i++){
  9.  var txt = (noRepetir(fdw));
  10.  document.write(txt+'<br />');
  11. }
Saludos (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #6 (permalink)  
Antiguo 06/02/2011, 10:42
Avatar de raxper  
Fecha de Ingreso: enero-2010
Ubicación: ------
Mensajes: 472
Antigüedad: 14 años, 10 meses
Puntos: 2
Respuesta: No repetir, Array mostrado al Azar

Igual se repiten :(
__________________
/^sleep:\/\//;
  #7 (permalink)  
Antiguo 06/02/2011, 10:46
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años, 7 meses
Puntos: 1485
Respuesta: No repetir, Array mostrado al Azar

la copia del array debes hacerlo al momento de crear la variable arr. o sea, arr = fdw.concat();. no puede ser dentro de la funcion debido el proceso que esta tomando. es decir, en la funcion creas la copia especificamente cuando el array este vacio.

__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.
  #8 (permalink)  
Antiguo 06/02/2011, 11:57
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años, 7 meses
Puntos: 1485
Respuesta: No repetir, Array mostrado al Azar

buenas...
verifica si esta version te funciona,supongo que es lo que @cronos quiso hacer.
Código:
Array.prototype.random = function(){
if(!this.clone) this.clone = this.concat(), this.clone.unshift(0, 0);
if(!this.length) [].splice.apply(this, this.clone);
return this.splice(Math.floor(Math.random()*this.length), 1)[0];
}
__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.

Última edición por zerokilled; 06/02/2011 a las 12:12
  #9 (permalink)  
Antiguo 06/02/2011, 14:03
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 5 meses
Puntos: 310
Respuesta: No repetir, Array mostrado al Azar

Hay varias cosas del código que no entiendo, a ver si me lo puedes explicar XD
1.- unshift() añade elementos al inicio del array, ¿para qué le añades dos 0?
2.- Vuelvo a toparme con apply... XD ¿Qué es exactamente lo que hace esa línea?
3.- Resuelta
Saludos (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #10 (permalink)  
Antiguo 06/02/2011, 15:55
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años, 7 meses
Puntos: 1485
con peras y manzanas; explicando las funciones apply y call

buenas...
veo que el tema de apply te trae loco desde un tema que se formulo recientemente. apply al igual que call, lo que hace es invocar una funcion como si fuese propia de otro objeto. o dicho de otro modo, call y apply cambia el propietario de la funcion por otro objeto. de modo que cada vez que en la funcion se utiliza la referencia this, dicha referencia representa el nuevo objeto. veamos un ejemplo:
Código:
var foo = {fn: function(){
console.log(this.bar); 
// console.log es una funcion de las consolas javascript para mostrar resultado en la consola ;
}, bar: true};

var boo = {bar: 'string'};
foo.fn.call(boo);
foo.fn.apply(boo);
en este ejemplo, notese que el objeto boo no contiene metodo pero tiene la propiedad bar al igual que el objeto foo. adiconalmente, notese que la funcion fn utiliza la referencia this para acceder al objeto que contiene la funcion. ahora, para invocar esa funcion como si fuese una funcion de boo, tendriamos que utilizar call o apply. si observas la consola de javascript, veras que la salida fue 'string'.

¿por qué existe dos funciones para el mismo propósito, o cual es la diferencia entre ellos? para ello, tendrias que ver la sipnosis de cada funcion.
Código:
fn.apply(object, array);
fn.call(object, arg1, ..., argN);
apply recibe dos argumentos, el objeto al cual se va aplicar la funcion y un array de valores. dicho array se tomaran como argumentos para la funcion aplicada al objeto. en contraste, call puede recibir uno o mas argumentos, siendo el primero el objeto y el resto los argumentos para la funcion aplicada al objeto.
Código:
var Rate = {
fixed: 1.07,
calc: function(value, add){
return this.fixed * value + add;
}};

var rate = {
fixed: 1.37
};

console.log(Rate.calc.call(rate, 3.14, 7));
console.log(Rate.calc.apply(rate, [2.3, 1.2]));
en este corto ejemplo, notese que el metodo calc recibe dos argumentos: value, add. al aplicar el metodo a otro objeto debemos tambien pasarle los parametros el cual lo puedes observar en call y apply.

proximo punto, ¿por que agregue dos ceros al inicio del array? como quizas sabras, splice modifica los arrays, ya sea agregar o eliminar elementos. el primer argumento de splice se refiere a partir de cual elemento del array se va a modificar, el segundo argumento es un conteo a partir del primer argumento, y los subsiguientes argumentos son los valores que se van a introducir al array. como veras, en el metodo del prototipo, la idea es restaurar el array con el original. no puedo utilizar concat porque dicho metodo no modifica el array, solo devuelve uno nuevo. adicional, tampoco puedes asignar un valor a this. o sea, ninguna de las siguientes lineas funciona.
Código:
this = this.clone.concat();
this = this.clone.slice(0, this.clone.length);
// notese que dice slice, no splice ;
la unica alternativ que me permite modificar el array original es splice o recorrer el clon con un bucle pero como el tema en particular es con splice entonces dejare a un lado el bucle. si hiciera lo siguiente me devuelve un resultado incorrecto:
Código:
this.splice(0, 0, this.clone);
// el array tendria como elemento otro array ;
// por ejemplo, [].splice(0,0, [0,1,2,3]) resultaria como ;
// [[0,1,2,3]] y lo que quiero lograr es [0,1,2,3] ;
por tanto, la solucion es hacer que splice introduzca los elementos al array. para ello me valgo de splice con apply. de modo que si no agrego al inicio los dos ceros, apply aplicaria la funcion de forma similar a lo siguiente.
Código:
this.clone = [0,1,2,3]; // asumiendo que dicho array es la copia ;
this.splice.apply(this, this.clone);
// la linea anterior seria similar a ;
this.splice(0,1,2,3);
notese el problema de la ultima linea, los primeros dos elementos del array estarian indicando a splice que debe comenzar por el primer elemento del array original y va a remover un solo elemento del original. el tercer argumento en adelante vendrian siendo los valores a introducir al array. por tanto, el resultado final en un array vacio seria [2,3]. ahi es donde juega el papel importante de los ceros introducidos al clon. es para que splice pueda introucir correctamente los valores del clon en el array original.

como observacion adicional, call no era apropiado en la solucion porque como iba a enumerar los argumentos a partir del array. de modo que apply hace esa tarea por mi.

hasta aqui llega la leccion de hoy...
saludos!
__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.

Última edición por zerokilled; 06/02/2011 a las 16:27 Razón: agregando enlace al tema
  #11 (permalink)  
Antiguo 06/02/2011, 16:30
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 5 meses
Puntos: 310
Respuesta: No repetir, Array mostrado al Azar

Realmente apply y call me traen loco desde bastante antes, pero hoy me dio por preguntar XD
Genial explicación ZK, te has tomado bastante tiempo en redactar todo eso ^^ Te agradezco todo lo que he aprendido hoy de ti (ha sido un día de provecho ) y también la paciencia que has tenido (seguramente yo no hubiera tenido tanta XD). Guardaré este post en favoritos porque no me extrañaría nada que tuviera que consultarlo de nuevo dentro de un mes
Gracias otra vez y ahí va un poquito de karma.
Saludos (:
PD: Me pareció muy ingenioso lo de añadir dos ceros, a lo mejor es una tontería pero me gusta como queda :3
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red

Etiquetas: repetir
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 18:37.