es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Fusionando elementos no nulos y no superpuestos de dos listas en Perl.

Estoy buscando un método limpio en Perl para fusionar una colección de listas. Todas tienen la misma longitud y consisten principalmente en ceros, pero también tienen segmentos contiguos cortos de entradas no nulas. Por ejemplo, aquí hay dos listas representativas de longitud 25:

@flags1 = qw( 0 0 0 0 21 22 23 0 0 0 0 0 0 0 0 41 42 43 0 0 0 0 0 0 0);
@flags2 = qw(11 12 13 0 0 0 0 0 0 0 0 0 0 31 32 33 0 0 0 0 0 51 52 53 0);

El objetivo es fusionar los elementos de @flags2 en @flags1 en todos los lugares donde un grupo contiguo de elementos no nulos en @flags2 reemplaza solo entradas nulas en @flags1. Si hay una superposición con cualquiera de los elementos no nulos de @flags1, se descarta el grupo contiguo asociado de valores no nulos en @flags2 en lugar de fusionarse.

Por lo tanto, para el ejemplo anterior, el grupo contiguo de valores 31, 32 y 33 en @flags2[13..15] se descarta porque una de las entradas, $flags2[15], no es cero y choca con el valor no nulo en $flags1[15]. La lista fusionada resultante deseada sería:

@merged = qw(11 12 13 0 21 22 23 0 0 0 0 0 0 0 0 41 42 43 0 0 0 51 52 53 0);

He experimentado con la recolección de elementos contiguos no nulos en una lista de listas y luego comparándolos usando ciclos for y condicionales if, pero es un desastre, y creo que será difícil para otros desarrolladores comprender la lógica. Si alguien pudiera proponer una solución más elegante, sería muy apreciado.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Una solución potencial a este problema usando Perl podría involucrar iterar a través de @flags1 y @flags2 simultáneamente usando un bucle for, y comparar los valores en cada índice. Si el valor en @flags1 es cero y el valor en @flags2 es diferente de cero, entonces podemos comenzar a recolectar un grupo contiguo de valores diferentes de cero en @flags2 hasta que lleguemos al final de la lista o a un valor diferente de cero en @flags1. Una vez que hayamos recolectado un grupo contiguo de valores diferentes de cero, podemos verificar si hay algún valor diferente de cero en @flags1 que se superponga con el grupo en @flags2. Si los hay, descartamos el grupo y continuamos. De lo contrario, reemplazamos los elementos correspondientes en @flags1 con el grupo de @flags2.

    Aquí hay un código de muestra que implementa este enfoque:

    my @flags1 = qw( 0  0  0  0 21 22 23  0  0  0  0  0  0  0  0 41 42 43  0  0  0  0  0  0  0);
    my @flags2 = qw(11 12 13  0  0  0  0  0  0  0  0  0  0 31 32 33  0  0  0  0  0 51 52  53 0);
    my @merged = @flags1;
    
    # Iterar a través de ambos arrays simultáneamente
    my $inicio_grupo = -1;
    for my $i (0..$#flags1) {
        # Si encontramos un valor diferente de cero en flags2...
        if ($flags2[$i] && !$inicio_grupo) {
            $inicio_grupo = $i;  # ...comenzar a recolectar un nuevo grupo
        }
        # Si estamos en medio de la recolección de un grupo y encontramos un valor diferente de cero en flags1...
        elsif ($inicio_grupo && $flags1[$i]) {
            $inicio_grupo = -1;  # ...descartar el grupo y comenzar de nuevo
        }
        # Si estamos en medio de la recolección de un grupo y encontramos el final del grupo...
        elsif ($inicio_grupo && (!$flags2[$i] || $i == $#flags1)) {
            # Verificar si hay algún valor diferente de cero que se superponga en flags1
            my $superposicion = 0;
            for my $j ($inicio_grupo..$i-1) {
                if ($flags1[$j]) {
                    $superposicion = 1;
                    last;
                }
            }
            # Si no hay valores diferentes de cero que se superpongan, reemplazamos las entradas correspondientes en @merged con el grupo de @flags2
            if (!$superposicion) {
                @merged[$inicio_grupo..$i-1] = @flags2[$inicio_grupo..$i-1];
            }
            $inicio_grupo = 0;
        }
    }
    
    print "@merged";  # Salida: 11 12 13 0 21 22 23 0 0 0 0 0 0 0 0 41 42 43 0 0 0 51 52 53 0
    

    Este código debería producir la lista fusionada deseada como salida. Tenga en cuenta que esta implementación podría potencialmente ser mejorada y optimizada aún más con pruebas y optimización adicionales.

Comments are closed.