2010-03-01 24 views
8

xuất hiện sau trong 2,6 mã Python tôi:Ugly kết hợp của biểu thức máy phát điện với vòng lặp for

for src, dst in ([s,d] for s in universe for d in universe if s != d): 

Tôi có thể làm tốt hơn nhiều? Những gì tôi đặc biệt không thích là tôi đang có hiệu lực xác định cùng một cặp hai lần, một lần cho vòng lặp for và một lần nữa cho biểu thức máy phát điện. Tôi không chắc chắn liệu tôi có muốn:

for src, dst in itertools.product(universe, universe): 
    if src != dst: 

Có cách nào để thể hiện vòng lặp này chính xác không?

universe là một danh sách, nếu có bất kỳ sự khác biệt nào. Thứ tự lặp lại không quan trọng.

+0

Loại thói quen nào yêu cầu/cho phép một sản phẩm chéo như thế này? –

+0

Tôi nghĩ rằng mã của bạn là tốt đẹp, ví dụ đầu tiên là rõ ràng hơn để hiểu hơn khác. – dalloliogm

+0

@Ignacio: Tôi đang xây dựng biểu đồ 2 chiều có các nút là các phần tử của 'vũ trụ' và sẽ được xử lý bởi một số phần mềm khác ở nơi khác mong đợi một tập hợp các cạnh. Tôi có mã để tính toán sự tồn tại và trọng lượng của mỗi cạnh: nếu nó giúp bạn có thể giả định đây là một hàm 'make_edge (src, dst)', trả về một mô tả. Các giải pháp sử dụng 'map' hoặc các hàm liên quan khác để gọi' make_edge' là hợp lý, và có lẽ là điều đúng đắn cần làm, nhưng việc xoay vòng lặp for thành hàm không ít lặp lại so với tôi đã có, vì vậy không sửa chữa niggle AFAIK. –

Trả lời

5

Bạn có thể sử dụng đơn giản lồng nhau cho-vòng:

for src in universe: 
    for dst in universe: 
     if src == dst: 
     continue 
     ... 

tôi muốn nói đây là dễ dàng nhất để đọc cú pháp trong trường hợp này.

+0

Bạn cũng có thể đúng. Tôi ghét nó khi mã hoàn toàn bắt buộc là đơn giản nhất ;-) –

+0

Chấp nhận câu trả lời này, mà tôi đọc là "không, bạn không thể làm * nhiều * tốt hơn" ... –

1

itertools.product có thể mất một "lặp lại" tranh cãi từ khóa nếu bạn muốn có trình tự giống như nhiều hơn một tham số:

itertools.product(universe, repeat=2) 

nó là một vấn đề quan điểm về việc liệu đây là dễ đọc hơn.

Bạn có thể thay thế mã ban đầu của bạn với:

for (src, dest) in filter(lambda (a,b): a!=b, itertools.product(universe, repeat=2)): 
    ... 
+0

Tốt. Tôi không biết bạn có thể làm điều đó. –

+0

Khi bạn đang sử dụng một 'bộ lọc' với một' lambda', nó không tốn nhiều chi phí để làm 'cho (src, dest) trong ((a, b) cho a, b trong itertools.product (vũ trụ, lặp lại = 2) nếu a! = b): '. ** LƯU Ý: ** Làm như vậy. Vâng. Quan điểm của tôi là cho phép OP quyết định cái nào là dễ đọc nhất. – JeromeJ

3

Tôi đề nghị giữ nó hoàn toàn chức năng hoặc hoàn toàn với comprehensions. Đây là một triển khai hoàn toàn có chức năng.

import itertools 
import operator 

def inner_product(iterable): 
    "the product of an iterable with itself" 
    return itertools.product(iterable, repeat=2) 

def same(pair): 
    "does this pair contain two of the same thing?" 
    return operator.is_(*pair) 

universe = 'abcd' 

pairs = inner_product(universe) 
unique_pairs = itertools.ifilterfalse(same, pairs) 
for pair in unique_pairs: 
    print pair 

""" 
('a', 'b') 
('a', 'c') 
('a', 'd') 
('b', 'a') 
('b', 'c') 
('b', 'd') 
('c', 'a') 
('c', 'b') 
('c', 'd') 
('d', 'a') 
('d', 'b') 
('d', 'c') 
""" 
+0

Tôi thích điều này về nguyên tắc. Trong thực tế, mã có thể được duy trì bởi những người không biết/không biết Python, vì vậy tôi không nghĩ rằng tôi dám thực sự sử dụng nó lần này. –

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