2012-01-07 39 views
13

tôi nhận thấy rằng itertools không (có vẻ như với tôi) có một chức năng có khả năng của các yếu tố interleaving từ một số đối tượng iterable khác (như trái ngược với nén chúng):Python có chức năng tích hợp cho các trình tạo/trình tự xen kẽ không?

def leaf(*args): return (it.next() for it in cycle(imap(chain,args))) 
tuple(leaf(['Johann', 'Sebastian', 'Bach'], repeat(' '))) => ('Johann', ' ', 'Sebastian', ' ', 'Bach', ' ') 

(Chỉnh sửa) Lý do tôi hỏi là vì Tôi muốn tránh những lần xuất hiện zip/flatten không cần thiết. Rõ ràng, định nghĩa của leaf là đủ đơn giản, nhưng nếu có một chức năng được xác định trước làm điều tương tự, tôi muốn sử dụng nó, hoặc một biểu thức máy phát rất rõ ràng. Có một chức năng như vậy được xây dựng trong, trong itertools, hoặc trong một số thư viện nổi tiếng khác, hoặc một biểu thức thành ngữ phù hợp?

Chỉnh sửa 2: Một định nghĩa thậm chí ngắn gọn hơn là có thể (bằng cách sử dụng functional gói):

from itertools import * 
from functional import * 

compose_mult = partial(reduce, compose) 
leaf = compose_mult((partial(imap, next), cycle, partial(imap, chain), lambda *args: args)) 
+6

Trong một lưu ý hoàn toàn không liên quan, tôi không thể không đề cập đến việc Bạch được đề cập là Johann, chứ không phải John. – 9000

+0

@ 9000: Khá - điều này đã rơi ra khỏi một bài kiểm tra đơn vị mà tôi lơ đãng viết nó vì nó là – Marcin

Trả lời

4

Các itertools roundrobin() recipe sẽ đã lựa chọn đầu tiên của tôi, mặc dù trong ví dụ chính xác của bạn nó sẽ tạo ra một chuỗi vô hạn, vì nó dừng lại với iterable dài nhất, không phải là ngắn nhất. Tất nhiên, nó sẽ dễ dàng để sửa chữa điều đó. Có lẽ nó có giá trị kiểm tra cho một cách tiếp cận khác nhau?

+0

Đó là loại điều tôi đã suy nghĩ, ngoại trừ việc (a) Tôi thích ngữ nghĩa về lá (b) định nghĩa của tôi ngắn gọn hơn. – Marcin

9

Bạn đang tìm kiếm được xây dựng trong zipitertools.chain.from_iterable để san bằng kết quả:

>>> import itertools 
>>> list(zip(['Johann', 'Sebastian', 'Bach'], itertools.repeat(' '))) 
[('Johann', ' '), ('Sebastian', ' '), ('Bach', ' ')] 
>>> list(itertools.chain.from_iterable(_)) 
['Johann', ' ', 'Sebastian', ' ', 'Bach', ' '] 

Lưu ý rằng tôi đã sử dụng list chỉ để buộc đầu ra đẹp. Sử dụng itertools tiêu chuẩn, triển khai thay thế cho leaf sẽ là:

leaf = lambda *a: itertools.chain.from_iterable(itertools.izip(*a)) # Python 2.x 
leaf = lambda *a: itertools.chain.from_iterable(zip(*a))   # Python 3.x 
+0

Sẽ không 'izip' được an toàn hơn? –

+0

@larsmans An toàn hơn theo cách nào? 'itertools.izip' đã bị xóa khỏi Python kể từ 3.0. – phihag

+1

OK. Tôi vẫn sống trong thế giới Python 2.x chủ yếu. –

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