Extraer subsecuencias enteras que comienzan con un número repetido

Extraer subsecuencias enteras que comienzan con un número repetido

Tengo un archivo que contiene una sola columna de números enteros. Quiero extraer de este archivo la lista de todas las subsecuencias contiguas (es decir, subsecuencias que ocurren en orden consecutivo) que comienzan con el mismo número dos veces seguidas y que tienen una longitud de 12 números enteros (incluidas las subsecuencias superpuestas).

Además, cualquier línea que no sea entera en el archivo debe ignorarse/eliminarse y si alguna secuencia llega al final de la entrada antes de alcanzar los 12 enteros, entonces la secuencia acortada aún debe generarse.

Por ejemplo, supongamos que mi archivo de entrada contiene los siguientes datos:

1
junk
1

1
2
3
4
4
5
6
7
8
9
10
11
12
13
14
15
15
16

Entonces la solución debería producir el siguiente resultado:

1 1 1 2 3 4 4 5 6 7 8 9
1 1 2 3 4 4 5 6 7 8 9 10
4 4 5 6 7 8 9 10 11 12 13 14
15 15 16

Observe que la junklínea y la línea vacía se ignoran, de modo que las tres primeras 1filas se tratan como contiguas.

Respuesta1

Aquí hay un script de Python que hace lo que quieres:

#!/usr/bin/env python2
# -*- coding: ascii -*-
"""extract_subsequences.py"""

import sys
import re

# Open the file
with open(sys.argv[1]) as file_handle:

    # Read the data from the file
    # Remove white-space and ignore non-integers
    numbers = [
        line.strip()
        for line in file_handle.readlines()
        if re.match("^\d+$", line) 
    ]

    # Set a lower bound so that we can output multiple lists
    lower_bound = 0
    while lower_bound < len(numbers)-1:

        # Find the "start index" where the same number
        # occurs twice at consecutive locations
        start_index = -1 
        for i in range(lower_bound, len(numbers)-1):
            if numbers[i] == numbers[i+1]:
                start_index = i
                break

        # If a "start index" is found, print out the two rows
        # values and the next 10 rows as well
        if start_index >= lower_bound:
            upper_bound = min(start_index+12, len(numbers))
            print(' '.join(numbers[start_index:upper_bound]))

            # Update the lower bound
            lower_bound = start_index + 1

        # If no "start index" is found then we're done
        else:
            break

Supongamos que sus datos están en un archivo llamado data.txt. Entonces podrías ejecutar este script así:

python extract_subsequences.py data.txt

Supongamos que su archivo de entrada data.txtse parece al siguiente:

1
1
1
2
3
4
5
6
7
8
9
10
11
12

Entonces su salida se vería así:

1 1 1 2 3 4 5 6 7 8 9 10
1 1 2 3 4 5 6 7 8 9 10 11

Para guardar la salida en un archivo, utilice la redirección de salida:

python extract_subsequences.py data.txt > output.txt

Respuesta2

AWKacercarse:

Considerando solo primero encontrados 2 números consecutivos idénticos, es decir, es adecuado para extracciones múltiples pero sin considerar la condición de que 2 números consecutivos idénticos puedan ir dentro de la secuencia seguida de 10 números bajo el segmento procesado.

awk 'NR==n && $1==v{ print v ORS $1 > "file"++c; tail=n+11; next }
     { v=$1; n=NR+1 }NR<tail{ print > "file"c }' file

Respuesta3

Primera variante - O(n)

awk '
/^[0-9]+$/{
    arr[cnt++] = $0;
}

END {
    for(i = 1; i < cnt; i++) {
        if(arr[i] != arr[i - 1])
            continue;

        last_element = i + 11; 
        for(j = i - 1; j < cnt && j < last_element; j++) {
            printf arr[j] " ";
        }
        print "";
    }
}' input.txt

Segunda variante - O(n * n)

awk '
BEGIN {
    cnt = 0;
}

/^[0-9]+$/{
    if(prev == $0) {
        arr[cnt] = prev;
        cnt_arr[cnt]++;
        cnt++;
    }
    
    for(i = 0; i < cnt; i++) {
        if(cnt_arr[i] < 12) {
            arr[i] = arr[i] " " $0; 
            cnt_arr[i]++;
        }
    }

    prev = $0;        
}

END {
    for(i = 0; i < cnt; i++)
        print arr[i];
}' input.txt

Producción

1 1 1 2 3 4 4 5 6 7 8 9
1 1 2 3 4 4 5 6 7 8 9 10
4 4 5 6 7 8 9 10 11 12 13 14
15 15 16

información relacionada