2015-05-21 26 views
5
def partition(n, iterable): 
    p = izip_longest(*([iter(iterable)] * n)) 
    r = [] 
    for x in p: 
     print(x) #I added this 
     s = set(x) 
     s.discard(None) 
     r.append(list(s)) 
    return r 

Điều này thực sự là trong một công việc đăng trên SO và là một newbie tôi nghĩ rằng nó là thú vị. Vì vậy, bạn sẽ có được kết quả như sau:Chức năng này hoạt động như thế nào? (Trình biến đổi Python)

partition(5, L) 
(1, 2, 3, 4, None) 
Out[86]: [[1, 2, 3, 4]] 

Đối với tôi đây là đã nhầm lẫn bởi vì tôi nghĩ izip_longest(*([iter(iterable)] * n)) sẽ chạy izip_longest chức năng trên một danh sách n lặp giống hệt nhau vì vậy tôi sẽ có dự kiến ​​đầu tiên công suất (1,1,1,1,1) và sau đó một đầu ra của (2,2,2,2,2) và cứ thế.

phiên bản Vì vậy, ngắn gọn câu hỏi của tôi, là những gì đang xảy ra với dòng này:

p = izip_longest(*([iter(iterable)] * n)) 

Phân tích nó tôi đã có thể nghĩ [iter (iterable)] * n tạo ra một danh sách dài n của iterables giống hệt tất cả chỉ vào cùng một thứ - đó là những gì nó làm trên dòng lệnh, nhưng điều đó dường như không phải là những gì nó làm ở đây dựa trên đầu ra được in ở trên.

Ngoài ra tôi nghĩ rằng * ở đầu ...longest(*... đã ở đó vì danh sách có độ dài không xác định nhưng tôi không nghĩ điều đó hoàn toàn hợp lý. Biểu tượng * đầu tiên thực hiện bên trong cuộc gọi hàm là gì? Có vẻ như nó chỉ đơn giản là chỉ ra một danh sách dài các đối số không xác định ...

Vì vậy, vào cuối ngày, tôi hoàn toàn bị mất. Ai đó có thể hướng dẫn tôi qua cú pháp này?

Cảm ơn rất nhiều về mọi đầu vào!


Cảm ơn tất cả các câu trả lời hữu ích, tất cả mọi người. Tôi không chắc liệu tôi có trả lời hay câu hỏi ở đây hay không, nhưng dường như tôi hiểu danh sách này sẽ làm điều tương tự cho các danh sách và bộ dữ liệu (tôi nhận ra các trình vòng lặp cũng sẽ áp dụng cho các từ điển, các lớp tùy chỉnh, các thứ khác .. .)

[L[i*n:(i+1)*n] for i in range(int(ceil(len(L)/float(n)))) ] 
+1

Bạn đã đọc [Làm thế nào để 'zip (* [iter (s)] * n)' hoạt động trong Python] (http://stackoverflow.com/questions/2233204/how- does-zipitersn-work-in-python)? –

+0

nó phá vỡ một danh sách lớn thành N danh sách nhỏ hơn .... điền Không có trong trường hợp độ dài danh sách không chia hết cho N ... danh sách con duy nhất có chứa bất kỳ 'None' nào là danh sách cuối –

+0

Thêm 'print (list (p))' để xem những gì 'izip_longest()' đã làm. – martineau

Trả lời

6

Given:

>>> li 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 

Có một thành ngữ Python phổ biến khi sử dụng zip kết hợp với iter* operator để phân chia danh sách thành danh sách phẳng thành danh sách các danh sách có độ dài n:

>>> n=3 
>>> zip(*([iter(li)] * n)) 
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14), (15, 16, 17), (18, 19, 20)] 

Tuy nhiên, nếu n không phải là một bội thậm chí của chiều dài tổng thể, danh sách cuối cùng được cắt ngắn:

>>> n=4 
>>> zip(*([iter(li)] * n)) 
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, 15), (16, 17, 18, 19)] 

Bạn có thể sử dụng izip_longest để sử dụng danh sách đầy đủ điền vào với một giá trị chọn để danh sách phụ không hoàn chỉnh:

>>> list(izip_longest(*([iter(li)] * n))) 
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, 15), (16, 17, 18, 19), (20, None, None, None)] 
+0

câu trả lời hay giải thích lý do tại sao anh ấy lại nhận được Không và tại sao lại sử dụng izip_longest :) +1 –

+0

@dawg thanks rất nhiều. Điều này thực sự tốt đẹp. – sunny

+1

Cần lưu ý rằng do hậu quả của cách thêm 'Không' bị xóa, các phép lặp có chứa 'None' không được hỗ trợ bởi hàm này. Ví dụ, 'phân vùng (2, [1,2, None, 4,5])' cho '[[1, 2], [4], [5]]'. Nó sẽ mạnh mẽ hơn khi sử dụng một giá trị được gửi tùy chỉnh, tôi nghĩ vậy. – jpmc26

6

iter(my_list) chuyển đổi một danh sách vào một iterable (có nghĩa là một trong những nơi yếu tố được tiêu thụ khi chúng được nhìn thấy)

[my_iter]*5 tạo ra một danh sách mới của [my_iter,my_iter,my_iter,my_iter,my_iter] trong đó tất cả quan điểm của my_iter với cùng chính xác iterator

zip(*[my_iter,my_iter,my_iter,my_iter,my_iter]) 

cũng giống như

zip(my_iter,my_iter,my_iter,my_iter,my_iter) 

(các splat chỉ đơn giản là giải nén một danh sách/tuple) mà về cơ bản chỉ trả về một danh sách 2d 5xlen(my_list)//5

bạn có thể đơn giản hóa nó với zip bình thường

#this method will have no `None` entries 
new_list_partitioned = zip(*[iter(big_list)]*N) + [big_list[-(len(big_list)%N):],] 
+0

nếu bạn nhìn vào câu hỏi của tôi, phần đó tôi nhận được. Những gì tôi đã không nhận được là lý do tại sao * ở phía trước [iter (... – sunny

+0

nó giải nén danh sách ... –

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