Lun Ago 21, 2006 8:35 am
|
 |
danimera
Perlero Adicto

|
Registrado: 23 Jun 2005
Mensajes: 244
Ubicación: Colombia
|
|
| Ordenar Arreglo en Perl |
|
|
Me van a Perdonar ustedes si es que Molesto mucho,y en principal Explorer Pero es que estoy haciendo un modulo que pronto publicare aqui y les agradecere mucho, Mi duda ahora es la siguiente
tengo el siguiente array
$datos[0] = "ID||apellido||edad";
$datos[1] = "01||Castro||16";
$datos[2] = "02||Gomez||21";
$datos[2] = "03||Diaz||20";
Pues la idea es que me de un segundo array ordenano por el segundo campo que es nombre de forma alfabetica
$datos_ordenados[0] = "ID||apellido||edad";
$datos_ordenados[1] = "01||Castro||16";
$datos_ordenados[2] = "03||Diaz||20";
$datos_ordenados[2] = "02||Gomez||21";
Tengo algo asi mas o menos
$campos =shift (@datos);
// Como ya se que quiero ordenar por apellidos, y que el segundo campo es el apellido entonces hago esto
($id_n,$apellido_n,$edad_n) = split(/\|\|/, $campos);
cant_reg = @datos;
$i = 1;
foreach $data (@datos){
($id,$apellido,$edad) = split(/\|\|/, $data); # esto seria como decir $datos[i];
($id_temp,$apellido_temp,$edad_temp) = split(/\|\|/, @datos[$i]); # esto seria como decir $datos[i+1] el dato que le sigue
if ($apellido <= $apellido_temp) { #aqui estaria haciendo la comparacion segun el metodo de intercambion si elemento(i) > elemento(i+1)
$temp = $data;
$j = $i-1;
$datos[$j] = $datos[$i];
$datos[$i] = $temp; #acabo de acer el intercambio, y asi continuara leyendo cada uno de los elementos y me los ordena
unshift @datos_ordenados, ($id."||".$apellido."||".$edad); # realmente esto no es que haga nada en si
}else{
push { @datos_ordenados, ($id."||".$apellido."||".$edad); # esto creo que menos
}
$i++;
}
unshift @datos, ($id_n."||".$apellido_n."||".$edad_n);
unshift @datos_ordenados, ($id_n."||".$apellido_n."||".$edad_n);
// Pero les aseguro que tengo algo malo ahi si uso en metodo de intercambio de burbuja que no tengo muy en claro como implementarlo ahi.
De todas manera el algoritmo me haria que @datos se ordenara el solo o eso pretendo, pero si me gustaria que me quedara ordenado en @datos_ordenados segun el campo que yo quiera en este caso use el apellido. |
|
|
|

Lun Ago 21, 2006 9:26 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4212
Ubicación: Valladolid, España
|
|
|
|
|
Con una transformada de Schwartz es fácil hacer una ordenación de un vector por el campo y la condición que quieras: | Perl: | #!/usr/bin/perl
@datos = qw(
ID||apellido||edad
01||Castro|| 16
02||Gomez|| 21
03||Diaz|| 20
);
@datos_a_ordenar = @datos[ 1 .. $ #datos ];
@datos_ordenados =
map { $_-> [0] }
sort{ $a-> [1] cmp $b-> [1] }
map { [ $_, (split '||')[1] ] }
@datos_a_ordenar;
unshift @datos_ordenados, $datos[0];
print join "\n", @datos_ordenados; | Salida: | Cita: | ID||apellido||edad
01||Castro||16
03||Diaz||20
02||Gomez||21 | En este caso, el campo es el 1 y se lo pasamos al split para que nos lo dé. Y la condición de comparación es '$a cmp $b' por lo que estamos ordenando alfabéticamente en orden ascendente.
Y de molestar, nada. Esta ha sido la excusa perfecta para colocar esta maravillosa construcción en este foro.
Ultima edición por explorer el Dom Ago 27, 2006 9:32 pm, editado 3 veces |
|

Lun Ago 21, 2006 9:27 am
|
 |
Perl user
Maestro Honorario

|
Registrado: 03 Nov 2004
Mensajes: 385
|
|
|
|
|
Después de un largo periodo de inactividad en foros... te dejo una pequeña respuesta, tu trabajo sería analizar como funciona, pero es sencillo.
| Código: |
#!/usr/bin/perl
use strict;
use warnings;
sub sort_func {
return ( split /\|\|/, $_[0] )[1];
}
my @data = qw( ID||apellido||edad
01||Castro||16
03||Diaz||20
02||Gomez||21 );
my @sorted = sort { sort_func( $a )
cmp
sort_func( $b )
} @data[ 1..$#data ];
print @sorted;
|
Saludos, |
|

Lun Ago 21, 2006 9:30 am
|
 |
Perl user
Maestro Honorario

|
Registrado: 03 Nov 2004
Mensajes: 385
|
|
|
|
|
Que tal explorer,
La Schwartzian transform generalmente se utiliza para estructuras complejas ( con referencias ) y cuya función para computar la transformación es cara, ya que bueno como podrás observar, genera un poquito de 'overhead' tras las llamadas a map/sort.
Para el problema de danimera puedes llamar directamente la función de comparación dentro del mismo bloque de sort, y así no generar tantas listas, ya que se trata de una lista plana.
Saludos, |
|

Lun Ago 21, 2006 10:02 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4212
Ubicación: Valladolid, España
|
|
|
|
|
A mí me da igual... tengo una máquina a quien le sobran megabytes y megaherzios. La seguiré usando sean las estructuras simples o complejas y el método de ordenación supere mi barrera metal de un simple sort.
Y en cuanto a la sobrecarga, estamos con el problema de siempre: intercambiar espacio por cálculos.
En la transformada se hacen 3 comparaciones y 3 llamadas a split, pero en un sort como el tuyo se hacen 3 comparaciones con 6 llamadas a la función sort_func con 6 llamadas a split.
Los números son casi los mismos, pero no escalan igual en cuanto el vector empieza a crecer. En ese caso, lo mejor para la solución de la función sort_func es 'memorizarla' con Memoize. Pero entonces estamos haciendo una ocupación de recursos de memoria, que es lo que la transformada ya hace con sus listas. Otra cosa sería hacer un benchmark, pero ahora no tengo tiempo  |
|

Lun Ago 21, 2006 10:51 am
|
 |
danimera
Perlero Adicto

|
Registrado: 23 Jun 2005
Mensajes: 244
Ubicación: Colombia
|
|
|
|
|
#!/usr/bin/perl
No quiero ser empalagoso Perl User ni Explorer,
La solucion de perl User la entiendo mas o menos lo que no entiendo es la comparacion en:
my @sorted = sort { sort_func( $a ) #que es esa $a
cmp # necesito una explicacion de esta funcion
sort_func( $b ) #que es esa $b
} @data[ 1..$#data ]; #esto significa que empieza desde el indice 1??¿?
No quiero molestarles la vida, pero no podria usar ninguna esta solucionesi no la entiendo perfectamente,
con Explorer
@datos_a_ordenar = @datos[ 1 .. $#datos ]; ?? #No entiendo aqui, el escoge a partir del elemento con indice 1
@datos_ordenados =
map { $_->[0] } # Que es la funcion map que hace???¿? sera que ejecuta por cala elemento de la lista las operaciones en el bloque?¿?
sort{ $a->[1] cmp $b->[1] } # Que sucede aqui? entiendo la funcion sort pero no $a->[0]
map { [ $_, (split '||')[1] ] } # Esto lo entiendo bien
@datos_a_ordenar;
unshift @datos_ordenados, $datos[0]; #OK
print join "\n", @datos_ordenados; #OK
SI me pueden explicar estas duditas les agradeceria de lo mejor mejor,, y les mostraria el resultado de tantas de mis preguntaderas en el FORO OK..  |
|

Lun Ago 21, 2006 11:24 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4212
Ubicación: Valladolid, España
|
|
|
|
|
| danimera escribió: | | @datos_a_ordenar = @datos[ 1 .. $#datos ]; ?? #No entiendo aqui, el escoge a partir del elemento con indice 1 | Sí, porque no quiero ordenar el primer registro, el que vale 'ID', pues de ese sé que siempre quiero que esté en primera posición en el resultado, así que los @datos_a_ordenar serán los @datos que van desde el registro 1 hasta el último.
| danimera escribió: | @datos_ordenados =
map { $_->[0] } # Que es la funcion map que hace???¿? sera que ejecuta por cala elemento de la lista las operaciones en el bloque?¿?
sort{ $a->[1] cmp $b->[1] } # Que sucede aqui? entiendo la funcion sort pero no $a->[1]
map { [ $_, (split '||')[1] ] } # Esto lo entiendo bien
@datos_a_ordenar; | La transformada de Schwartz es un proceso de 3 pasos:- transformación del elemento del vector original a otro elemento de vector en el que el componente a comparar está aislado de la complejidad que posee al estar dentro del elemento original, más, el propio elemento original
- Ordenación de ese vector recien creado
- Nueva transformación del vector ordenado en que sólo nos dedicamos a extraer los elementos originales
Como el vector fue ordenado por el campo que nos interesaba, esto es como si hubieramos indexado un vector con un índice externo. El resultado es la lectura ordenada de esos índices y sus valores acompañantes, que son los elementos originales.
- $_->[0] : extraemos el elemento original que fue almacenado en el segundo map
- $a->[1] : como los elementos a comparar son vectores anónimos de dos componentes, tenemos que acceder, de forma indirecta, con un '->', y con un [1] para indicar que nos referimos al segundo componente del vector.
P.D. Estamos en el foro Experto... algunas cosas no las explico porque se suponen sobreentendidas. |
|

Lun Ago 21, 2006 1:41 pm
|
 |
Perl user
Maestro Honorario

|
Registrado: 03 Nov 2004
Mensajes: 385
|
|
|
|
|
| explorer escribió: | A mí me da igual... tengo una máquina a quien le sobran megabytes y megaherzios. La seguiré usando sean las estructuras simples o complejas y el método de ordenación supere mi barrera metal de un simple sort.
Y en cuanto a la sobrecarga, estamos con el problema de siempre: intercambiar espacio por cálculos.
En la transformada se hacen 3 comparaciones y 3 llamadas a split, pero en un sort como el tuyo se hacen 3 comparaciones con 6 llamadas a la función sort_func con 6 llamadas a split.
Los números son casi los mismos, pero no escalan igual en cuanto el vector empieza a crecer. En ese caso, lo mejor para la solución de la función sort_func es 'memorizarla' con Memoize. Pero entonces estamos haciendo una ocupación de recursos de memoria, que es lo que la transformada ya hace con sus listas. Otra cosa sería hacer un benchmark, pero ahora no tengo tiempo  |
Totalmente de acuerdo, las máquinas hoy en día son tan poderosas que reducciones así no importan mucho, pero aunque sea poderosa, siempre hay cambios de un algoritmo a otro, siempre es SIEMPRE, posiblemente en estructuras pequeñas ( dudo mucho que el ejemplo de danimera sea muy enorme ) pues es demasiado trivial.
Pero el diseño de algoritmos "eficientes" si es importante, ahora bien... las operaciones realizadas por la schwartzian transform aparte de las que mencionaste es el uso de map , map genera listas nuevas recuerda.
El punto clave de esta serie de comentarios es pues, destacar cuando una transformada de schwartz es necesaria, en palabras del mismo Randal, que fué lo que cité arriba.
Pero totalmente de acuerdo, eres libre de usar lo que mas te acomode.
Saludos, |
|

Lun Ago 21, 2006 5:22 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4212
Ubicación: Valladolid, España
|
|
|
|
|
| Lo que pasa es que... como me aprendí la transformada de Schawrtz leyendo el libro 'Perl Cookbook', con un ejemplo sencillo, pues que al final lo aplicas hasta donde no debes. |
|
Powered by phpBB © 2001, 2005 phpBB Group
|