Ich bin neu in Python und versuche, eine verschachtelte Schleife zu erstellen. Ich habe eine sehr große Datei (1,1 Millionen Zeilen) und möchte damit eine Datei erstellen, die jede Zeile zusammen mit den nächsten N Zeilen enthält, zum Beispiel mit den nächsten 3 Zeilen:

1    2
1    3
1    4
2    3
2    4
2    5

Im Moment versuche ich nur, die Loops mit Rownumbers anstelle der Strings zum Laufen zu bringen, da es einfacher zu visualisieren ist. Ich habe mir diesen Code ausgedacht, aber er verhält sich nicht so, wie ich es möchte:

with open('C:/working_file.txt', mode='r', encoding = 'utf8') as f: 
for i, line in enumerate(f):
     line_a = i
     lower_bound = i + 1
     upper_bound = i + 4
     with open('C:/working_file.txt', mode='r', encoding = 'utf8') as g:
        for j, line in enumerate(g):
            while j >= lower_bound and j <= upper_bound:
                line_b = j
                j = j+1
                print(line_a, line_b)

Anstelle der Ausgabe, die ich wie oben möchte, gibt es mir Folgendes:

990     991
990     992
990     993
990     994
990     992
990     993
990     994
990     993
990     994
990     994

Wie Sie sehen können, wird die innere Schleife für jede Zeile in der äußeren Schleife mehrmals wiederholt. Es scheint, dass es nur eine Iteration pro Zeile in der äußeren Schleife geben sollte. Was vermisse ich?

EDIT: Meine Frage wurde unten beantwortet. Hier ist der genaue Code, den ich letztendlich verwendet habe:

from collections import deque
from itertools import cycle
log = open('C:/example.txt', mode='w', encoding = 'utf8') 
try:
    xrange 
except NameError: # python3
    xrange = range

def pack(d):
    tup = tuple(d)
    return zip(cycle(tup[0:1]), tup[1:])

def window(seq, n=2):
    it = iter(seq)
    d = deque((next(it, None) for _ in range(n)), maxlen=n)
    yield pack(d)
    for e in it:
        d.append(e)
        yield pack(d)

for l in window(open('c:/working_file.txt', mode='r', encoding='utf8'),100):
    for a, b in l:
        print(a.strip() + '\t' + b.strip(), file=log)
5
raspberry_door 10 Dez. 2013 im 04:05

4 Antworten

Beste Antwort

Basierend auf einem Fensterbeispiel aus alten Dokumenten können Sie etwas verwenden mögen:

from collections import deque
from itertools import cycle

try:
    xrange 
except NameError: # python3
    xrange = range

def pack(d):
    tup = tuple(d)
    return zip(cycle(tup[0:1]), tup[1:])

def window(seq, n=2):
    it = iter(seq)
    d = deque((next(it, None) for _ in xrange(n)), maxlen=n)
    yield pack(d)
    for e in it:
        d.append(e)
        yield pack(d)

Demo:

>>> for l in window([1,2,3,4,5], 4):
...     for l1, l2 in l:
...         print l1, l2
...
1 2
1 3
1 4
2 3
2 4
2 5

Grundsätzlich können Sie Ihre Datei an das Fenster übergeben, um das gewünschte Ergebnis zu erzielen:

window(open('C:/working_file.txt', mode='r', encoding='utf8'), 4)
5
alko 10 Dez. 2013 im 00:44

Basierend auf der Antwort von alko würde ich vorschlagen, das Rezept window unverändert zu verwenden

from itertools import islice

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    
    for elem in it:
        result = result[1:] + (elem,)
        yield result

for l in window([1,2,3,4,5], 4):
    for item in l[1:]:
        print l[0], item
1
Peter Gibson 10 Dez. 2013 im 01:17

Sie können dies mit Scheiben tun. Dies ist am einfachsten, wenn Sie zuerst die gesamte Datei in eine Liste einlesen:

with open('C:/working_file.txt', mode='r', encoding = 'utf8') as f: 
    data = f.readlines()

for i, line_a in enumerate(data):
    for j, line_b in enumerate(data[i+1:i+5], start=i+1):
        print(i, j)

Wenn Sie ändern, dass die Zeilen anstelle der Zeilennummern gedruckt werden, können Sie das zweite enumerate löschen und einfach for line_b in data[i+1:i+5] ausführen. Beachten Sie, dass das Slice das Element am Startindex enthält, jedoch nicht das Element am Endindex, sodass es höher sein muss als Ihre aktuelle Obergrenze.

1
lvc 10 Dez. 2013 im 00:33

Ich denke, der einfachste Weg, dieses Problem zu lösen, wäre, Ihre Datei in ein Wörterbuch einzulesen ...

my_data = {}
for i, line in enumerate(f):
    my_data[i] = line

Danach können Sie tun

for x in my_data:
    for y in range(1, 4):
        print my_data[x], my_data[x + y]

Wie geschrieben, lesen Sie Ihre Million-Zeilen-Datei millionenfach für jede Zeile ...

0
Paul Becotte 10 Dez. 2013 im 00:35