2008-12-24 68 views
34

例如,Python中的文件是可迭代的 - 它們迭代文件中的行。我想要統計行數。是否有任何內置的方式來獲取python中的迭代長度?

一個快速的方法是做到這一點:

lines = len(list(open(fname))) 

然而,這種加載整個文件到內存中(一次)。這相當於破壞了迭代器的目的(它只需要將當前行保留在內存中)。

這不起作用:

lines = len(line for line in open(fname)) 

如發電機不具有的長度。

有沒有辦法做到這一點,定義一個計數函數?編輯:澄清,我明白,整個文件將不得不閱讀!我只是不希望它在內存中一次=)。

+0

來計算您將在內存中加載文件的行數! – hasen 2008-12-24 06:00:29

+0

列表(所有序列類型)也是可迭代的。你的意思是「迭代器」 – hop 2008-12-24 07:09:49

+4

@hasen:是的,但不是一次全部。 – Claudiu 2008-12-24 07:52:26

回答

53

短通過迭代迭代和重複計數,數沒有。這就是使它成爲可迭代的而不是列表的原因。這甚至不是一個特定於python的問題。看看傳統的鏈表數據結構。查找長度是一個O(n)操作,它涉及迭代整個列表以查找元素的數量。

正如mcrute上面提到的,你或許可以減少你的函數:

def count_iterable(i): 
    return sum(1 for e in i) 

當然,如果你定義你自己的迭代對象可以隨時實現__len__好自己,保持一個元素計數的地方。

+0

這可以通過itertools.tee() – hop 2008-12-25 20:16:53

+0

@hop改進:小心解釋一下? – 2011-04-18 14:00:44

18

如果需要行的計數,你可以做到這一點,我不知道有什麼更好的方式來做到這一點:

line_count = sum(1 for line in open("yourfile.txt")) 
0

如果你仔細想想,我們會怎麼建議你找到一個文件中的行數而不讀取整個文件的換行符?當然,你可以找到文件的大小,如果你可以保證一行的長度是x,你可以得到一個文件中的行數。但是,除非你有某種限制,否則我不會看到這是如何工作的。另外,因爲iterables可以是無限長的...

7

絕對不是,因爲iterables不能保證是有限的。

考慮這個完全合法發生器功能:

def forever(): 
    while True: 
     yield "I will run forever" 

試圖計算此函數的長度與len([x for x in forever()])顯然行不通。

正如您所指出的,迭代器/生成器的大部分目的是能夠處理大型數據集而無需將其全部加載到內存中。你無法立即獲得長度的事實應該被認爲是一種折衷。

8

我用這個重新定義了一段時間:

def len(thingy): 
    try: 
     return thingy.__len__() 
    except AttributeError: 
     return sum(1 for item in iter(thingy)) 
5

cardinality包提供了一個高效count()功能和一些相關的功能,計數和檢查可迭代的大小:http://cardinality.readthedocs.org/

import cardinality 

it = some_iterable(...) 
print(cardinality.count(it)) 

它在內部使用enumerate()collections.deque()將所有實際的循環和計數邏輯移動到C級,導致相對於for在Python中循環。

2

事實證明,這個common problem實施的解決方案。考慮使用more_itertools中的ilen()函數。

more_itertools.ilen(iterable) 

打印文件中的行數(我們使用的with上下文管理器安全地處理關閉文件)的一個例子:

# Example 
import more_itertools 

with open("foo.py", "r+") as f: 
    print(more_itertools.ilen(f)) 

# Output: 433 

此示例返回相同的結果早些時候提出的解決方案共線在一個文件中:

# Equivalent code 
with open("foo.py", "r+") as f: 
    print(sum(1 for line in f)) 

# Output: 433 
0

我沒有在我的一些代碼,發現關於正多少圖的兩種常見方法之間的測試頂點有,看看生成列表中哪些計數元素的方法變得更快。 Sage有一個生成器圖(n),它生成n個頂點上的所有圖。我創建了兩個函數,它們以兩種不同的方式獲取迭代器獲得的列表長度,並使用time.time()函數爲每個函數計時(平均超過100次測試運行)。的功能如下:

def test_code_list(n): 
    l = graphs(n) 
    return len(list(l)) 

def test_code_sum(n): 
    S = sum(1 for _ in graphs(n)) 
    return S 

現在我時間每個方法

import time 

t0 = time.time() 
for i in range(100): 
    test_code_list(5) 
t1 = time.time() 

avg_time = (t1-t0)/10 

print 'average list method time = %s' % avg_time 


t0 = time.time() 
for i in range(100): 
    test_code_sum(5) 
t1 = time.time() 

avg_time = (t1-t0)/100 

print "average sum method time = %s" % avg_time 

平均列表方法時間= 0.0391882109642

平均總和方法時間= 0.0418473792076

因此,通過這種方式計算n = 5個頂點上的圖的數量,列表方法稍微快一點(儘管100次測試運行不是很好的樣本大小)。但是,當我增加了列表的長度由上N = 7個頂點試圖圖形計算(即改變的曲線圖(5)〜圖(7)),其結果是這樣的:

平均列表方法時間= 4.14753051996

平均求和方法時間= 3.96504004002

在這種情況下,求和方法稍快。總而言之,這兩種方法的速度大致相同,但差異可能取決於列表的長度(也可能僅僅是我平均超過100次測試運行,這並不是很高 - 會花費很長時間除此以外)。

相關問題