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.

Cómo encontrar los índices de patrones de sub-listas en Perl.

Tengo una lista más larga cuyos elementos son símbolos de varios caracteres, por ejemplo:

@c = qw(iim v7 v7 iM iv7 iM <strong>im iv7 iv7 bviiM</strong> im biio iim bviim biiM biim bviM bviM ivm iih v7 v7 v7 iiim iiih vi7 iim v7 v7 iM iv7 iM <strong>im iv7 bviiM</strong> im biio iim bviim bviim iiio iim v7 v7 v7 vm i7 ivM iiih vi7);

Me gustaría encontrar los índices en esta lista que coincidan con sub-listas del tipo S1+ S2+ S3+, donde el “+” significa que coincida una o más veces. Entonces, por ejemplo, el patrón de sub-lista (im iv7 bviiM) coincidiría tanto con (im iv7 iv7 bviiM) como con (im iv7 bviiM) como se muestra en negrita anteriormente. El código proporcionaría los índices 6, 7, 8, 9 para la primera coincidencia y 32, 33, 34 para la segunda.

A simple vista, esto no parece ser difícil, y he intentado implementarlo con una variedad de métodos, incluyendo expresiones regulares, pero hasta ahora me ha vencido. Si hay una forma sencilla de hacer esto, estaría agradecido por cualquier ayuda.

Tags:  

Answer

  1. Avatar for davy.ai

    Para resolver este problema, una posible manera es iterar a través de la lista y usar una expresión regular para verificar si el elemento actual coincide con el patrón S1+ S2+ S3+. Podemos usar el operador de coincidencia no codicioso ? para asegurarnos de encontrar la coincidencia más corta posible. Una vez que encontramos una coincidencia, registramos los índices y continuamos la búsqueda desde el siguiente elemento.

    Aquí está una implementación utilizando Perl:

    my $pattern = qr/(im iv7 bviiM)+?/;
    
    my @indices;
    my $i = 0;
    while ($i < @c) {
        my $sublist = "";
        while ($c[$i] =~ /^$pattern/ and $i < @c) {
            $sublist .= "$& ";
            $i++;
        }
        if ($sublist) {
            push @indices, ($i - scalar(split / /, $sublist)) .. ($i - 1);
        } else {
            $i++;
        }
    }
    
    print "@indices\n";  # imprime "6 7 8 9 32 33 34"
    

    Explicación:

    • Definimos el patrón usando el operador qr//, que nos permite almacenar una expresión regular en una variable para su uso posterior. El patrón (im iv7 bviiM)+? coincide con los tres símbolos en secuencia, una o más veces, de manera no codiciosa.
    • Inicializamos una lista vacía @indices para almacenar los índices coincidentes y comenzamos a iterar a través de la lista con una variable de índice $i.
    • En cada iteración, verificamos si el elemento actual $c[$i] coincide con el patrón con la expresión regular /$pattern/. Si coincide, lo agregamos a la sublista actual e incrementamos el índice para continuar la búsqueda desde el siguiente elemento. Si no coincide, pasamos al siguiente elemento.
    • Si encontramos una sublista no vacía, la dividimos por espacios usando split / /, $sublist, contamos el número de elementos con scalar y restamos eso al índice actual $i para obtener el rango de índices que coincidieron con la sublista. Insertamos este rango en @indices.
    • Una vez que hemos procesado todos los elementos, imprimimos @indices.

Comments are closed.