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 junk
línea y la línea vacía se ignoran, de modo que las tres primeras 1
filas 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.txt
se 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
AWK
acercarse:
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