Foros del Web » Programando para Internet » PHP »

Cambio de array+rand a array_rand

Estas en el tema de Cambio de array+rand a array_rand en el foro de PHP en Foros del Web. Hola tengo un pequeño problema con los indices de un array. Mi código original es: Código PHP: $valor = $citas [ rand ( 0 ,( ...
  #1 (permalink)  
Antiguo 30/05/2008, 08:47
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Pregunta Cambio de array+rand a array_rand

Hola tengo un pequeño problema con los indices de un array.

Mi código original es:

Código PHP:
$valor=$citas[rand(0,(count($citas)-2))]; 
y quiero eliminar ese rand y count para convertirlo en un array_rand, algo como

Código PHP:
$valor=$citas[array_rand($citas)];# Falla porque no es de 0 a n-2, solo es de 0 a n 
o otra posibilidad
Código PHP:
$valor=$citas[array_rand($citas)-2];#Falla porque es de -2 a n-2 
No se me ocurre como poner el indice para que los valores estren entre 0 y n-2 y que se utilice el array_rand.

Es algo sencillo, pero no doy con ello.
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #2 (permalink)  
Antiguo 30/05/2008, 11:34
Avatar de eft0  
Fecha de Ingreso: junio-2003
Ubicación: Santiago - Chile
Mensajes: 635
Antigüedad: 20 años, 10 meses
Puntos: 9
Respuesta: Cambio de array+rand a array_rand

Por que quieres poner el -2? Podrias mostrarnos el arreglo citas que valores tiene y como esta formado.
__________________
eft0's stuff! - http://estebanfernandez.net
  #3 (permalink)  
Antiguo 30/05/2008, 11:46
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Pregunta Respuesta: Cambio de array+rand a array_rand

Veamos, este código es la simplificación de uno mas complicado.

Digamos que tengo un fichero frases.template con 6 frases tal que:
Código PHP:
Frase1
Frase2
Frase3
Frase4
Frase5
Frase6 
Ese fichero es leido asi:

Código PHP:
$citassplit("\n",$GLOBALS[html]->template('base','citas')); 
Por lo que, por cada salto de linea se agrega un valor al array citas.

El array contendra:
Código PHP:
Array ( 
             [
0] => Frase1 
             
[1] => Frase2 
             
[2] => Frase3 
             
[3] => Frase4 
             
[4] => Frase5 
             
[5] => Frase6 
             
[6] =>  ) 
Observese, que $citas[6] sera vacío porque el ultimo salto de linea en el fichero tambien se cuenta.

Luego para 6 valores, tenemos 7 posiciones de array (del 0 al 6), luego count($citas) devuelve 7, y el rand se haría entre 0 y 7, puesto que la 7 no existe hay que restar un valor y como la 6 esta vacía, debemos restar otro. De ahi el -2 que me da problemas, ya que si no hubiese ese -2 podría hacer el array_rand() sin problemas de límites.
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #4 (permalink)  
Antiguo 30/05/2008, 11:51
Avatar de deet  
Fecha de Ingreso: mayo-2005
Ubicación: Córdoba - Argentina
Mensajes: 269
Antigüedad: 18 años, 11 meses
Puntos: 1
Respuesta: Cambio de array+rand a array_rand

deberías restar primero 2 al numero de items totales y luego realizar el random sobre ese valor:

$num = sizeof($citas) - 2;

valor=$citas[array_rand($num)];

de la manera que tu lo planteas si array_rand() te arroja el valor 0, al restarle -2 queda -2. Está bien si te arroja un valor mayor a 2
  #5 (permalink)  
Antiguo 30/05/2008, 11:56
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

Esa es una solución pero no la mejor. Imagínate que no son citas lo que hay, si no millones de números primos (por ejemplo).

Tendría que hacer un sizeof() de millones!! Y eso es mas lento. La cuestión es minimizar funciones para disminuir la complejidad del algoritmo.

Se me acaba de ocurrir otra posibilidad y es que al split, puesto que trocea por expresiones regulares, si le pongo un "\n." (con el punto), para trocear estará obligado a tener un carácter después, y en el caso de la ultima linea no existe ninguno después del \n

algo así:
$citas= split("\n.",$GLOBALS[html]->template('base','citas'));
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #6 (permalink)  
Antiguo 30/05/2008, 12:11
Avatar de Derus  
Fecha de Ingreso: julio-2007
Mensajes: 9
Antigüedad: 16 años, 9 meses
Puntos: 0
De acuerdo Respuesta: Cambio de array+rand a array_rand

si quieres que sea hasta n-2 utilizando la funcion array_rand no se me ocurre otra cosa que acotar el array quitandole las dos ultimas entradas..

Código:
unset ($citas[count($citas)-1]);
unset ($citas[count($citas)-1]);
$valor=$citas[array_rand($citas)];
  #7 (permalink)  
Antiguo 30/05/2008, 12:15
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

El unset esta bien pero ya se utilizaría dos veces el count(), aunque la segunda vez se podría guardar el valor y solo utilizarse una, pero aun así, se utiliza y es como si fuera un "pecado" para este problema.
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #8 (permalink)  
Antiguo 30/05/2008, 12:17
Avatar de Derus  
Fecha de Ingreso: julio-2007
Mensajes: 9
Antigüedad: 16 años, 9 meses
Puntos: 0
Respuesta: Cambio de array+rand a array_rand

$ahorrando=count($citas);
unset ($citas[$ahorrando-1]);
unset ($citas[$ahorrando-2]);
$valor=$citas[array_rand($citas)];

(solucionado? el count que tendrias que utilizar a partir de ahora para manejar el array seria ($ahorrando-3) )
  #9 (permalink)  
Antiguo 30/05/2008, 12:22
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

Es lo que te decía "pecas" en un count() que tiene complejidad algoritmica n (suponiendo tiempo de procesado constante).
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #10 (permalink)  
Antiguo 30/05/2008, 12:24
Avatar de Derus  
Fecha de Ingreso: julio-2007
Mensajes: 9
Antigüedad: 16 años, 9 meses
Puntos: 0
Respuesta: Cambio de array+rand a array_rand

Entonces ardere en el infierno... jej
nose tio , no se me ocurre otra .. ¿usas algun programa para medir los tiempos del algoritmo o el rendimiento?
  #11 (permalink)  
Antiguo 30/05/2008, 12:25
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

Retiro mi propuesta de slice con el punto, la acabo de probar y no es válida, porque se cortaría también el carácter que implica al punto.

EDIT: Los calculos de los que hablo son puramente matemáticos, hay muchos libros sobre ellos y artículos, simplemente busca en google "Complejidad algorítmica" o libros relacionados con algoritmica.

Si quieres pruebas o benchmarks hay bastantes y realizarte los propios para medir tiempos tampoco es muy complicado.
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #12 (permalink)  
Antiguo 30/05/2008, 12:30
Avatar de deet  
Fecha de Ingreso: mayo-2005
Ubicación: Córdoba - Argentina
Mensajes: 269
Antigüedad: 18 años, 11 meses
Puntos: 1
Respuesta: Cambio de array+rand a array_rand

esto relantizaría lo mismo que count?

$num = array_slice($citas,0, -2);

valor=$citas[array_rand($num)];
  #13 (permalink)  
Antiguo 30/05/2008, 12:38
Avatar de radamantys  
Fecha de Ingreso: agosto-2006
Mensajes: 46
Antigüedad: 17 años, 7 meses
Puntos: 1
Respuesta: Cambio de array+rand a array_rand

prueba con esto

Código PHP:
do
{
   
$valor $citas[array_rand($citas)]
}while(empty(
$valor)); 
Si los va a usar en arrays grandes la posibilidad de que caiga en el ultimo es muy pequeña, por lo que la posibilidad de que hagas array_rand 2 veces es muy baja.

Tambien puedes hacer

Código PHP:
array_slice($citas0, -1);

$valor $citas[array_rand($citas)]; 
De todas formas si te interesa tanto la velocidad y las complejidades deberias saber que es mas rapido
usar mt_rand que array_rand

Código PHP:
   $i mt_rand[0count($citas)-2];
   
$valor $citas[$i]; 
creo que array_rand puede ser mas lento que usar count y mt_rand juntos

Saludos
Edit: No he visto el ultimo mensaje de deet, hemos escrito el mismo codigo.
  #14 (permalink)  
Antiguo 30/05/2008, 12:38
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

El problema es que array_slice devuelve un mixed y al pasearla array_rand la convierte a un array de una sola posición. Prueba a compilarlo y veras lo que pasa ;)
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #15 (permalink)  
Antiguo 30/05/2008, 12:43
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

El do while es buena intentona, pero estas haciendo un salto condicional, lo que hace que el pipeline (cauce) avance en la etapa de captura de instrucción y decodificación de operandos con el riesgo de que si se produce el fallo (aunque existe poca posibilidad) el cauce debe vaciarse y eso en N ejecuciones tiene muchísima latencia.

EDIT: el mt_rand lo contemple de hecho lo mejor sería
$quotes = explode("\n",$GLOBALS[html]->template('base','quotes')); # Si no usamos regex explode es mas efectivo
$valor=$quotes[mt_rand(0,(sizeof($quotes)-2))];#mt_rand +sizeof

El problema de esta solución es que tenemos el sizeof o el count y "pecamos" XD
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #16 (permalink)  
Antiguo 30/05/2008, 13:32
Avatar de radamantys  
Fecha de Ingreso: agosto-2006
Mensajes: 46
Antigüedad: 17 años, 7 meses
Puntos: 1
Respuesta: Cambio de array+rand a array_rand

No se que tienes planeado en hacer en PHP (un supercodigo XD) para darle tanta importancia a la complejidad de los algoritmos y de las funciones de PHP.

Para tener en cuenta la complejidad estariamos hablando de vectores muy grandes(millones), por lo que mi primera propuesta anterior no seria tan mala, las posibilidades de que caiga en el ultimo serian de 1/millones. De todas formas a ver esta:

Código PHP:

$i 
array_rand($citas);
$valor = !empty($citas[$i]) ? $citas[$i] : $citas[$i-1]; 
A ver esta. Solo usas el array_rand una vez, en caso (infinitesimo) de que caigas en la posicion vacía, escogera el valor anterior. Esta vez el "problema" seria de que la ultima posicion tendria una pequeña ventaja de ser seleccionada (2/millones de posiblidades XD).
  #17 (permalink)  
Antiguo 30/05/2008, 13:38
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

Esta solución que propones también es muy buena solución, pero también le podemos sacar pegas.

En el caso de que cayera en el valor vacío, estarías condicionando a que el último valor tuviera mas probabilidad de aparecer (si, en un millón, es poca probabilidad, pero y en 10 posiciones?), la probabilidad estaría trucada.
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
  #18 (permalink)  
Antiguo 30/05/2008, 14:53
Avatar de radamantys  
Fecha de Ingreso: agosto-2006
Mensajes: 46
Antigüedad: 17 años, 7 meses
Puntos: 1
Respuesta: Cambio de array+rand a array_rand

Vale, esta bien, tu ganas, aceptamos windows como sistema operativo... XD. En serio quiero ver que estas haciendo cuando este acabado. XD

Si el vector tiene pocas posiciones, usar sizeof o count no deberia ser problema. En caso de que uses vectores grandes, mis propuestas anteriores estan bien.

Deberias saber de antemano la posiciones de tu vector, o por lo menos si es muy grande o no. Habia por ahi en PHP una funcion que calculaba el espacio en byte que ocupaba una variable. Esta funcion creo que no consumira mucho tiempo, tendra una complejidad baja. Por lo que podrias usarla para saber si tu vector es muy grande o no y dependiendo de ello usar unos metodos u otros.

De todas formas tu problema principal es ese elemento del vector vacío deberias concentrarte en solucionarlo y no tendrias tantos problemas en el futuro. Es muy raro que la funcion explode coloque un ultimo elemento en blanco, a no ser que la cadena a partir tenga espacios en blanco al final. Prueba esto a ver si desaparece la posicion vacia del vector:

Código PHP:
$quotes explode("\n",trim($GLOBALS[html]->template('base','quotes'))); 
Asi quitas los espacios en blanco al final y al principio de la cadena, despues usa el explode, con un poco de suerte no deberia aparecer la ultima posicion vacia

Última edición por radamantys; 30/05/2008 a las 15:01
  #19 (permalink)  
Antiguo 30/05/2008, 15:35
Avatar de shakaran  
Fecha de Ingreso: agosto-2005
Ubicación: España - Ciudad Real
Mensajes: 374
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: Cambio de array+rand a array_rand

Y el ganador es.... ¡radamantys!

Problema SOLUCIONADO. La verdad es que te has currado un montón cada solución y le has dado al coco muchísimo. Me enorgullece ver que existe un alto nivel en este foro.

La solución con trim+explode es idónea y permite utilizar el array_random() o mt_rand()+sizeof o count para la otra parte.

Muchas gracias a todos los que lo intentaron y me ayudaron.

PD: No parece que haya de momento mejor solución pero si alguna mente avezada consigue mejor solución, siempre es bienvenida.

Offtopic: he googleado un poco sobre el tamaño de las variables, pero solo he encontrado referencias a strlen, ¿me podrias dar un poquito mas de info o sitio por donde empezar a buscar?
__________________
Quijost Backend Engineer - www.quijost.com - Hosting rápido, eficiente y profesional
Blog: www.shakaran.net
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 19:16.