【问题标题】:How to get every element in a list of list of lists?如何获取列表列表中的每个元素?
【发布时间】:2013-05-24 12:07:24
【问题描述】:

我正在为我的作业制作一个心脏游戏,但我不知道如何获取列表列表中的每个元素:

>>>Cards = [[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C],["JH"]],[["7D"]]]

我想到的是:

for values in cards:
    for value in values:

但我想我刚刚得到了有 2 个列表的元素。如何计算卡片中包含 3 和 1 的列表?

【问题讨论】:

  • 我编辑了您的代码以添加一个额外的",因为它丢失了。你为什么要恢复那个编辑?
  • 你需要一些递归来以一种干净的方式实现你想要的。
  • 所有卡片的深度都相同吗?然后你只需要去那里。
  • 看起来你有一个列表列表,但还没有关闭最后的括号。
  • @Erika Sawajiri 最后一项['7D'] 不是出错了吗?不应该是[['7D']]?

标签: python


【解决方案1】:

像这样:

>>> Cards = [[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C"],["JH"]],["7D"]]
>>> from compiler.ast import flatten
>>> flatten(Cards) 
['QS', '5H', 'AS', '2H', '8H', '7C', '9H', '5C', 'JH', '7D']

正如 nacholibre 指出的那样,compiler 包已被弃用。这是flatten的来源:

def flatten(seq):
    l = []
    for elt in seq:
        t = type(elt)
        if t is tuple or t is list:
            for elt2 in flatten(elt):
                l.append(elt2)
        else:
            l.append(elt)
    return l

【讨论】:

  • 太棒了!我不知道这存在。
  • 我不认为他们打算像这样使用该功能,但如果它有效...... :)。
  • 重要:Deprecated since version 2.6: The compiler package has been removed in Python 3.
  • @Hans 但你的 flatten 函数将分离所有元素,如 7 和 C。我想要的是 7C
  • 会吗?我认为它只会迭代列表和元组,而不是字符串。
【解决方案2】:

略显晦涩的oneliner:

>>> [a for c in Cards for b in c for a in b]
['QS', '5H', 'AS', '2H', '8H', '7C', '9H', '5C', 'JH', '7', 'D']

您可能想为 a、b 和 c 提供更具描述性的名称。

【讨论】:

  • 开始部分似乎是正确的。但是7和d是分开的
  • @blubber 问题是它们没有统一嵌套(这是存储游戏数据的一种奇怪方式......)
  • 是的,我现在明白了。那么你不能使用它,它只适用于规则形成的列表。
  • @ErikaSawajiri 列表中的最后一项应该是 [['7D']],是不是错字?
【解决方案3】:

如果您的卡片嵌套不方便:

>>> Cards = [[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C"],["JH"]],["7D"]]
>>> def getCards(cardList,myCards=[]): #change this to myCards, and pass in a list to mutate this is just for demo
        if isinstance(cardList,list):
            for subList in cardList:
                getCards(subList)
        else:
            myCards.append(cardList)
        return myCards
>>> getCards(Cards)
['QS', '5H', 'AS', '2H', '8H', '7C', '9H', '5C', 'JH', '7D']

将递归遍历列表并找到所有元素。这些是我比较所选flattern 方法与我的性能的一些时间:

>>> print(timeit.timeit(r'getCards([[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C"],["JH"]],["7D"]],[])',setup="from clas import getCards"))
5.24880099297
>>> timeit.timeit(r'flatten([[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C"],["JH"]],["7D"]])',setup="from compiler.ast import flatten")
7.010887145996094

【讨论】:

    【解决方案4】:

    您的列表是一个不完整的嵌套列表,因此您可以先将其设为矩形,例如using the procedure explained here,然后将生成的numpy.ndarray 展平。

    如果最后一个元素 ['7D'] 是 [['7D']],则下面的“ifs”也不是必需的(那么其他答案也可以)。

    import numpy as np
    collector = np.zeros((3,3,3),dtype='|S20')
    
    for (i,j,k), v in np.ndenumerate( collector ):
        try:
            if not isinstance(cards[i], str):
                if not isinstance(cards[i][j], str):
                    collector[i,j,k] = cards[i][j][k]
                else:
                    collector[i,j,0] = cards[i][j]
            else:
                collector[i,0,0] = cards[i]
        except IndexError:
            collector[i,j,k] = ''
    
    print collector[collector<>''].flatten()
    

    【讨论】:

      【解决方案5】:

      使用生成器,可以编写更易读的flatten 实现:

      def flatten(l):
          if isinstance(l, list):
              for e1 in l:
                  for e2 in flatten(e1):
                      yield e2
          else:
              yield l
      

      或者,如果您使用的是 Python 3.3,它添加了 yield from 语法:

      def flatten(l):
          if isinstance(l, list):
              for e in l:
                  yield from flatten(e)
          else:
              yield l
      

      结果:

      >>> list(flatten([[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C"],["JH"]],[["7D"]]]))
      ['QS', '5H', 'AS', '2H', '8H', '7C', '9H', '5C', 'JH', '7D']
      

      【讨论】:

        【解决方案6】:

        使用 2 个嵌套的itertools.chain 来展平列表:

        In [32]: Cards
        Out[32]: [[['QS', '5H', 'AS'], ['2H', '8H'], ['7C']], [['9H', '5C'], ['JH']], ['7D']]
        
        In [33]: from itertools import chain
        
        In [34]: [k for k in chain.from_iterable([i for i in chain.from_iterable(Cards)])]
        Out[34]: ['QS', '5H', 'AS', '2H', '8H', '7C', '9H', '5C', 'JH', '7', 'D']
        

        【讨论】:

          【解决方案7】:

          此解决方案对于任何类型的嵌套列表或元组都非常健壮(要添加其他可迭代类型,只需在下面的代码中添加更多 or isinstance(...)

          它只是递归调用一个展开自身的函数:

          def unfold(lst):
              output = []
              def _unfold(i):
                  if isinstance(i, list) or isinstance(i, tuple):
                      [_unfold(j) for j in i]
                  else:
                      output.append(i)
              _unfold(lst)
              return output
          
          print unfold(cards)
          #['QS', '5H', 'AS', '2H', '8H', '7C', '9H', '5C', 'JH', '7D']
          

          【讨论】:

            【解决方案8】:

            使用 Rosetta Code 中的 Flatten a list 您可以:

            >>> def flatten(lst):
                return sum( ([x] if not isinstance(x, list) else flatten(x)
                         for x in lst), [] )
            
            >>> Cards = [[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C"],["JH"]],["7D"]]
            >>> flatten(Cards)
            ['QS', '5H', 'AS', '2H', '8H', '7C', '9H', '5C', 'JH', '7D']
            >>> 
            

            该解决方案仅展平嵌套列表 - 而不是元组或字符串。

            【讨论】:

              【解决方案9】:
              from itertools import chain, imap
              
              l= [[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C"],["JH"]],[["7D"]]]
              
              k = list(chain.from_iterable(imap(list, l)))
              m = list(chain.from_iterable(imap(list, k)))
              
              print m
              

              输出:['QS','5H','AS','2H','8H','7C','9H','5C','JH','7D']

              Itertools 太棒了!

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-02-17
                • 1970-01-01
                • 2014-12-16
                • 2017-08-22
                • 2017-12-01
                • 2015-07-15
                • 1970-01-01
                相关资源
                最近更新 更多