2010-10-19 39 views
6

tôi có một danh sách như sau:Python: xác định chiều dài của chuỗi các mặt hàng bình đẳng trong danh sách

l = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 

Tôi muốn xác định độ dài của một chuỗi các mặt hàng như nhau, tức là để xem danh sách cho tôi muốn đầu ra là:

[(0, 6), (1, 6), (0, 4), (2, 3)] 

(hoặc định dạng tương tự).

Tôi đã nghĩ đến việc sử dụng một số defaultdict nhưng nó đếm số lần xuất hiện của mỗi mục và tích lũy nó cho toàn bộ danh sách, vì tôi không thể có nhiều hơn một khóa '0'.

Ngay bây giờ, giải pháp của tôi trông như thế này:

out = [] 
cnt = 0 

last_x = l[0] 
for x in l: 
    if x == last_x: 
     cnt += 1 
    else: 
     out.append((last_x, cnt)) 
     cnt = 1 
    last_x = x 
out.append((last_x, cnt)) 

print out 

Tôi tự hỏi nếu có một cách pythonic hơn để làm điều này.

Trả lời

13

Bạn hầu như chắc chắn muốn sử dụng itertools.groupby:

l = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 
answer = [] 
for key, iter in itertools.groupby(l): 
    answer.append((key, len(list(iter)))) 

# answer is [(0, 6), (1, 6), (0, 4), (2, 3)] 

Nếu bạn muốn làm cho nó bộ nhớ hiệu quả hơn, nhưng thêm phức tạp, bạn có thể thêm một chức năng chiều dài:

def length(l): 
    if hasattr(l, '__len__'): 
     return len(l) 
    else: 
     i = 0 
     for _ in l: 
      i += 1 
     return i 

l = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 
answer = [] 
for key, iter in itertools.groupby(l): 
    answer.append((key, length(iter))) 

# answer is [(0, 6), (1, 6), (0, 4), (2, 3)] 

Lưu ý mặc dù rằng tôi đã không đánh giá độ dài() chức năng, và nó khá có thể nó sẽ làm chậm bạn xuống.

+0

Bạn có thể tăng tốc độ mệnh đề 'else:' bằng cách thay thế những gì được hiển thị với hai dòng sau: 'cho i, _ trong liệt kê (l, 1): pass' theo sau là' return i'. – martineau

3

câu trả lời của Mike là tốt, nhưng itertools._grouper trả về bởi groupby sẽ không bao giờ có một phương pháp __len__ vì vậy không có thử nghiệm điểm cho nó

tôi sử dụng sum(1 for _ in i) để có được chiều dài của itertools._grouper

>>> import itertools as it 
>>> L = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 
>>> [(k, sum(1 for _ in i)) for k, i in it.groupby(L)] 
[(0, 6), (1, 6), (0, 4), (2, 3)] 
+1

. . . rất đẹp! – mshsayem

Các vấn đề liên quan