Ich habe eine Datei, die eine einzelne Spalte mit Ganzzahlen enthält. Ich möchte aus dieser Datei die Liste aller zusammenhängenden Teilfolgen (d. h. Teilfolgen, die in aufeinanderfolgender Reihenfolge auftreten) extrahieren, die zweimal hintereinander mit derselben Zahl beginnen und eine Länge von 12 Ganzzahlen haben (einschließlich überlappender Teilfolgen).
Darüber hinaus sollten alle nicht ganzzahligen Zeilen in der Datei ignoriert/entfernt werden, und wenn eine beliebige Sequenz das Ende der Eingabe erreicht, bevor 12 Ganzzahlen erreicht sind, sollte die verkürzte Sequenz trotzdem ausgegeben werden.
Angenommen, meine Eingabedatei enthält die folgenden Daten:
1
junk
1
1
2
3
4
4
5
6
7
8
9
10
11
12
13
14
15
15
16
Dann sollte die Lösung die folgende Ausgabe erzeugen:
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
Beachten Sie, dass die junk
Zeile und die leere Zeile ignoriert werden, sodass die ersten drei 1
Zeilen als zusammenhängend behandelt werden.
Antwort1
Hier ist ein Python-Skript, das macht, was Sie wollen:
#!/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
Angenommen, Ihre Daten befinden sich in einer Datei namens data.txt
. Dann könnten Sie dieses Skript wie folgt ausführen:
python extract_subsequences.py data.txt
Angenommen, Ihre Eingabedatei data.txt
sieht folgendermaßen aus:
1
1
1
2
3
4
5
6
7
8
9
10
11
12
Ihre Ausgabe würde dann folgendermaßen aussehen:
1 1 1 2 3 4 5 6 7 8 9 10
1 1 2 3 4 5 6 7 8 9 10 11
Um die Ausgabe in einer Datei zu speichern, verwenden Sie die Ausgabeumleitung:
python extract_subsequences.py data.txt > output.txt
Antwort2
AWK
Ansatz:
Es werden nur die ersten zwei identischen aufeinanderfolgenden Zahlen berücksichtigt, d. h. es ist für mehrere Extraktionen geeignet, jedoch ohne Berücksichtigung der Bedingung, dass innerhalb der folgenden 10-Zahlen-Folge unter dem verarbeiteten Slice zwei identische aufeinanderfolgende Zahlen vorkommen können.
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
Antwort3
Erste 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
Zweite 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
Ausgabe
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