2009-11-05 55 views
6

Tôi có một danh sách các hàng, ví dụ:cách mã một chức năng tương tự như itertools.product trong python 2.5

A=[(1,2,3), (3,5,7,9), (7)] 

và muốn tạo ra tất cả các hoán vị với một mục từ mỗi tuple.

1,3,7 
1,5,7 
1,7,7 
... 
3,9,7 

Tôi có thể có bất kỳ số lượng bộ và bộ nào có thể có bất kỳ số phần tử nào. Và tôi không thể sử dụng itertools.product() vì python 2.5.

+0

Lưu ý rằng bạn sẽ cần phải xác định lại A. Khi bạn nói 'A = [(1,2,3), (3,5,7,9), (7)]' the '(7) 'ở cuối được đánh giá như một số nguyên, không phải là một tuple. Do đó nó không thể lặp lại, và 'product (* A)' sẽ ném một TypeError. Nếu bạn nói 'A = (1,2,3), (3,5,7,9), (7,)]' thì 'sản phẩm (* A)' sẽ hoạt động. – unutbu

+0

Ok, tôi hiểu, nhưng đây là một ví dụ quá đơn giản. Tôi có A dưới dạng danh sách các bộ 3 số. Nhưng tôi muốn loại bỏ danh sách bên ngoài và nhận được A = danh sách các bộ 3 số. Làm thế nào để làm điều đó? Tốt hơn để làm điều này một câu hỏi python mới bắt đầu tôi nghĩ. – lgwest

Trả lời

13

docs của itertools.product có một ví dụ về làm thế nào để thực hiện nó trong py2.5:

def product(*args, **kwds): 
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy 
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 
    pools = map(tuple, args) * kwds.get('repeat', 1) 
    result = [[]] 
    for pool in pools: 
     result = [x+[y] for x in result for y in pool] 
    for prod in result: 
     yield tuple(prod) 
+0

Bên cạnh đó '(* args, repeat = 1)' không hoạt động trong Python 2.5 ... – ephemient

+0

cố định rằng, tôi đã vô tình sao chép ví dụ từ tài liệu py3.1. – SilentGhost

4

Các tài liệu itertools chứa mã đầy đủ cho thấy những gì mỗi chức năng tương đương với. Việc triển khai producthere.

+0

Cảm ơn, tôi đã nhanh chóng hỏi tôi nghĩ. – lgwest

5
def product(*iterables): 
    """ Equivalent of itertools.product for versions < 2.6, 
     which does NOT build intermediate results. 
     Omitted 'repeat' option. 
     product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy 
    """ 
    nIters = len(iterables) 
    lstLenths = [] 
    lstRemaining = [1] 
    for i in xrange(nIters-1,-1,-1): 
     m = len(iterables[i]) 
     lstLenths.insert(0, m) 
     lstRemaining.insert(0, m * lstRemaining[0]) 
    nProducts = lstRemaining.pop(0) 

    for p in xrange(nProducts): 
     lstVals = [] 

     for i in xrange(nIters): 
      j = p/lstRemaining[i]%lstLenths[i] 
      lstVals.append(iterables[i][j]) 
     yield tuple(lstVals) 
2

Khi chơi xung quanh với máy phát điện, tôi cũng tìm thấy một phiên bản của itertools.product, và nó gần như là nhanh như (bản địa) phiên bản thư viện, trong khi được 100% tương thích với nó, và nó không xây dựng kết quả trung gian :

def product(*args, **kwds): 
    "Alternative fast implementation of product for python < 2.6" 
    def cycle(sequence, uplevel): 
     while True: 
      vals = next(uplevel) # advance upper level, raises if done 
      it = iter(sequence) # (re-)start iteration of current level 
      try: 
       while True: yield vals + (next(it),) 
      except StopIteration: 
       pass 

    step = iter(((),))    
    for pool in map(tuple, args)*kwds.get('repeat', 1): 
     step = cycle(pool, step) # build stack of iterators 
    return step 

Với python 2.7.3, tôi thấy hiệu suất thực sự tốt (thường chỉ chậm hơn khoảng 5-10 lần với mức sử dụng bộ nhớ).

>>> import itertools as itt 
>>> timeit for _ in itt.product(range(20), range(3), range(150)): pass 
1000 loops, best of 3: 221 µs per loop 
>>> timeit for _ in product(range(20), range(3), range(150)): pass 
1000 loops, best of 3: 1.14 ms per loop 
+0

Sử dụng thử/ngoại trừ kết thúc vòng lặp không phải là tuyệt vời. Về cơ bản, bạn dựa vào một lỗi để đoản mạch vòng lặp của bạn. –

+0

Tôi không đồng ý với lời buộc tội rằng tôi đang lợi dụng điều kiện "lỗi" để thoát khỏi vòng lặp - 'StopIteration' là điều kiện hợp lệ để kiểm tra cấu trúc vòng lặp vì nó được sử dụng nội bộ bất cứ khi nào vòng lặp bị chấm dứt. Lưu ý rằng ngoại lệ và 'StopIteration' nói riêng có sử dụng rộng hơn một chút trong Python so với C++, cf. cũng là Zen của Python. – summentier

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