2016-06-11 13 views
5

Vì vậy, ví dụ nếu tôi có danh sáchTìm số nguyên tố liên tiếp đều giống nhau trước khi họ thay đổi

a = [1,1,1,2,2] 
b = [1,1,2,2,2] 
c = [2,1,1,1,1] 

tôi muốn để có được những vệt dài nhất của phần tử đầu tiên trong danh sách, ví dụ như vậy a sẽ cung cấp cho 3, b sẽ cung cấp cho 2 và c sẽ cung cấp cho 1. Tôi biết tôi có thể tạo ra một vòng lặp while và đếm streak theo cách đó, nhưng tôi đã tự hỏi nếu có một cách thanh lịch hơn để làm điều này?

+0

nếu bạn muốn tính tất cả cá thể của phần tử đầu tiên thì bạn có thể sử dụng a.count ([0]) – amitnair92

+0

Cụm từ "dài nhất * streak * 'của phần tử đầu tiên" là bit mơ hồ: cho dù câu trả lời cho '[1,1,1,2,2,1,1,1,1]' là 3 hoặc 4. – ninjagecko

Trả lời

6

bạn có thể làm một cái gì đó như thế này:

numStreak = ([a[0] == n for n in a]+[False]).index(False) 

(điều này cũng làm cho chắc chắn rằng nếu tất cả các yếu tố này như là yếu tố đầu tiên, chỉ số này trả về giá trị đúng)

UPDATE: một hiệu quả hơn (nhưng ít thanh lịch?) phiên bản

from itertools import takewhile 
len([1 for _ in takewhile(lambda x:x==a[0], a)]) 

hoặc tốt hơn một chút (UPDATE 2) @ đề nghị vaultah của:

sum(1 for _ in takewhile(lambda x:x==a[0], a)) 
+2

Điều này rất thông minh nhưng nó làm tôi buồn vì nó lặp lại toàn bộ danh sách ngay cả khi độ dài chỉ là 1. –

+0

Tôi đã thêm một phiên bản hiệu quả hơn nhưng có lẽ hơi kém thanh lịch – DomTomCat

+0

Phải là 'tổng (1 cho _ trong khi chờ đợi (lambda x: x == a [0], a))' – vaultah

3

Bạn có thể sử dụng groupby và tổng hợp có bao nhiêu mặt hàng nằm trong nhóm đầu tiên cho mỗi:

a = [1,1,1,2,2] 
b = [1,1,2,2,2] 
c = [2,1,1,1,1] 

from itertools import groupby 

for l in [a,b,c]: 
    print(sum(1 for _ in next(groupby(l), [[], []],)[1])) 

Hoặc sử dụng takewhile:

from itertools import takewhile 

for l in [a, b, c]: 
    print(sum((1 for _ in takewhile(lambda x: x == l[0], l)))) 

Nếu dữ liệu của bạn luôn luôn là một danh sách, tuple, vv . trong nhóm , bạn có thể kiểm tra giá trị falsey thay vì đặt mặc định trong next(..:

for l in [a, b, c]: 
    print(sum(1 for _ in next(groupby(l))[1]) if l else 0) 
+0

Tôi không hoàn toàn hiểu '[[], []]' phần. Nó đang làm gì? – DSM

+0

@DSM, nếu một lần lặp trống có thể được chuyển, bạn sẽ nhận được lỗi 'StopIteration' –

+0

Ah, được rồi, tôi thấy những gì bạn đang làm cho đến bây giờ. Nếu chúng ta biết chúng ta có trình tự, tôi có thể chỉ cần thêm 'if l else 0' vào cuối, nhưng điều đó sẽ không xử lý trường hợp của một biến lặp chung. – DSM

0

Bạn có thể sử dụng NumPy:

>>> import numpy as np 
>>> a = [1,1,1,2,2] 
>>> b = [1,1,2,2,2] 
>>> c = [2,1,1,1,1] 
>>> def runs(data): 
... return np.split(data, np.where(np.diff(data) != 0)[0]+1) 
... 
>>> for e in a,b,c: 
... runs(np.array(e)) 
... 
[array([1, 1, 1]), array([2, 2])] 
[array([1, 1]), array([2, 2, 2])] 
[array([2]), array([1, 1, 1, 1])] 

Sau đó chỉ cần lấy chiều dài của chạy đầu tiên:

>>> for e in a,b,c: 
... len(runs(np.array(e))[0]) 
... 
3 
2 
1 

Hoặc, trong Python, chỉ cần sử dụng một vòng lặp while:

>>> def r(a): 
... i=1 
... while a[0]==a[i]: i+=1 
... return i 
... 
>>> r(a) 
3 
>>> r(b) 
2 
>>> r(c) 
1 
1

Một lớp lót cho đường? Hãy nhắm mục tiêu ...

a = [5,5,5,5,8] 
list(np.ediff1d(a)).count(0)+1 
>>> 4 
Các vấn đề liên quan