簡體   English   中英

將python的列表理解擴展為嵌套for循環 - 奇怪的結果

[英]Expanding python's list comprehension into nested for loops — strange results

我遇到這個函數來返回數組中N值的每個組合:

def combs(a, n):
   if n == 0:
       return [[]]
   else:
       return [(x + [y]) for x in combs(a,n-1) for y in a]

為了我自己的理解,我嘗試使用嵌套for循環將其轉換為函數:

def combinations(array,n):
    if n == 0:
        return [[]]
    else:
        for i in array:
            for j in combinations(array, n-1):
                return [j + [i]]

但是我得到的結果與我預期的不同。

>>> threes = ['aA','bB','cC']
>>> 
>>> combs(threes,2)
[['aA', 'aA'], ['aA', 'bB'], ['aA', 'cC'], ['bB', 'aA'], ['bB', 'bB'], ['bB', 'cC'], ['cC', 'aA'], ['cC', 'bB'], ['cC', 'cC']]
>>> 
>>> combinations(threes,2)
[['aA', 'aA']]
>>> 

我已嘗試各種版本的行return [j+[i]]都沒有成功。 這里有些例子:

                return (j + [i])

Traceback (most recent call last):
  File "...", line 24, in <module>
    print(combinations(threes,2))
  File "...", line 16, in combinations
    return (j + [i])
TypeError: can only concatenate str (not "list") to str

                return j + [i]

Traceback (most recent call last):
  File "...", line 24, in <module>
    print(combinations(threes,2))
  File "...", line 16, in combinations
    return j + [i]
TypeError: can only concatenate str (not "list") to str

為什么第一個函數的列表理解返回的東西與擴展的嵌套for循環版本不同?

將第一個函數的list-comprehension和return值轉換為嵌套for循環策略的正確(運行)方法是什么?

如果你真的想要使它等效,那么你需要做一次return 當你執行理解時,你在某種程度上以原子方式創建列表,即列表在完全構造之前是不可訪問的//在列表理解(構造)完成之前無法訪問列表。 要在沒有列表理解的情況下執行它,您需要填充一個可變容器,然后在最后執行一次返回:

def combinations(array,n):
    if n == 0:
        return [[]]
    else:
        result = []
        for i in array:
            for j in combinations(array, n-1):
                result.append(j + [i])
        return result

這是解決問題的有效方法,但我也會探索創建生成器函數。 不同於通常的情況下,你只能return從函數一次,發電機可以讓你yield從功能多倍。

如果您不希望在創建期間阻止,您不希望強制使用特定容器,或者通常在您想要簡化某些邏輯時,此策略很有用。 此外,如果您只需要迭代結果並且實際上不需要一次完整列表,那么它具有不將整個序列加載到內存中的額外優勢。

一般來說,我發現這些優點是一個引人注目的理由,可以創建像這樣的大多數函 對於簡短列表,理解或標准列表創建(如上例所示)足以解決問題。

需要注意的是,您可能需要根據應用程序的需要將結果打包到容器中。 這是因為生成器按需創建每個新條目,並簡單地流式傳輸結果:

def combinations(array,n):
    if n == 0:
        yield []
    else:
        for i in array:
            for j in combinations(array, n-1):
                yield j + [i]

>>> print(list(combinations(['aA','bB','cC'], 2)))
[['aA', 'aA'], ['bB', 'aA'], ['cC', 'aA'], ['aA', 'bB'], ['bB', 'bB'], ['cC', 'bB'], ['aA', 'cC'], ['bB', 'cC'], ['cC', 'cC']]

如果你想使用具有生成器優點的理解,那么你可以使用生成器理解(使用( )而不是[ ] )和語句的yield from

def combs(a, n):
   if n == 0:
       yield []
   else:
       yield from (x + [y] for x in combs(a, n - 1) for y in a)
> The list comprehension always returns a result list. 
> 
> But in your nested loop case you are not returning list so little
> modify in your case
> 
> 
  def combinations(array,n):
>     if n == 0:
>         return [[]]
>     else:
          result=[]
>         for i in array:
>             for j in combinations(array, n-1):
>                 result.append([j + [i]])
>         return result 
 In this you are returning the list of all iterations ..

暫無
暫無

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

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