Extrahieren ganzzahliger Teilfolgen, die mit einer wiederholten Zahl beginnen

Extrahieren ganzzahliger Teilfolgen, die mit einer wiederholten Zahl beginnen

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 junkZeile und die leere Zeile ignoriert werden, sodass die ersten drei 1Zeilen 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.txtsieht 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

AWKAnsatz:

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

verwandte Informationen