簡體   English   中英

避免計算整個笛卡爾積(python itertools)

[英]avoid computing whole cartesian product (python itertools)

我的目標是找到nxn矩陣(2 <= n <= 15)中對角線的任何排列。 矩陣由零和一組成。

目前我是這樣的:

  indices = [[j for j, x in enumerate(row) if x == 1] 
                for row in self.matrix]
  cart = list(itertools.product(*indices))
  cart = [list(tup) for tup in cart]
  cart = filter(lambda dia: len(list(set(dia))) == len(dia), cart)
  return cart

如果矩陣不是太大,則可以正常工作,否則將失敗並顯示:MemoryError

那么有沒有辦法避免購物車的整個計算呢? 這樣,例如找到一個排列,計算就停止了嗎?

只需不對itertools.product的結果調用list並使用itertools.ifilter代替filter使所有評估變得懶惰:

from itertools import ifilter, product

indices = [[j for j, x in enumerate(row) if x == 1]  for row in self.matrix]
cart = product(*indices)
found_cart = next(ifilter(lambda dia: len(set(dia)) == len(dia), cart), None)

next返回第一種情況,即ifilter中的謂詞為True或在沒有匹配項的情況下返回None

找到匹配項后, 計算將停止。

您可以簡化代碼的最后一部分,使其僅返回第一個答案:

def foo(matrix):
    indices = [[j for j, x in enumerate(row) if x == 1] for row in matrix]

    # this part is changed, very simple and efficient now
    for dia in itertools.product(*indices):
        if len(set(dia)) == len(dia):
            return dia

換句話說,不要對filter和lambda以及其他所有內容都那么聰明-這是不必要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM