簡體   English   中英

Python嵌套循環 - 接下來的N行

[英]Python nested loop - get next N lines

我是Python的新手,並試圖做一個嵌套循環。 我有一個非常大的文件(110萬行),我想用它來創建一個文件,每行包含接下來的N行,例如接下來的3行:

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

現在我只是試圖讓循環使用rownumbers而不是字符串,因為它更容易可視化。 我想出了這個代碼,但它的表現並不像我想要的那樣:

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)

它不是我想要的輸出,而是給我這個:

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

正如您所看到的,內循環對外循環中的每一行迭代多次。 看起來外循環中每行只應該有一次迭代。 我錯過了什么?

編輯:我的問題在下面得到解答,這是我最終使用的確切代碼:

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)

基於舊文檔的窗口示例,您可以使用以下內容:

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)

演示:

>>> 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

所以,基本上你可以將文件傳遞給窗口以獲得所需的結果:

window(open('C:/working_file.txt', mode='r', encoding='utf8'), 4)

你可以用切片做到這一點。 如果您首先將整個文件讀入列表,這是最簡單的:

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)

當您將其更改為打印行而不是行號時,您可以刪除第二個enumerate ,只for line_b in data[i+1:i+5]執行。 請注意,切片包含起始索引處的項目,但包括結束索引處的項目,因此需要比當前上限高一個。

根據alko的回答,我建議不加修改地使用window配方

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

我認為解決這個問題的最簡單方法是將文件讀入字典......

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

完成后你就可以做到

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

正如所寫,你正在為每行讀取百萬行文件...

由於這是一個非常大的文件,您可能不希望一次將其全部加載到內存中。 因此,為了避免多次讀取一行,這就是你所做的。

  • 創建一個包含N個元素的列表,其中N是要讀取的下一行的數量。

    • 閱讀第一行時,將其添加到列表中的第一項。
    • 將嵌套線添加到第一個和第二個項目。
    • 等等每行
  • 當該列表中的項目達到長度N時,將其取出並將其附加到輸出文件。 並在末尾添加一個空項目,這樣您仍然有一個N項列表。

這樣你只需要讀取每一行,而不必將整個文件加載到內存中。 你只需要保持最大N! 記憶中的線條。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM