我正在为我的任务制作一个心脏游戏,但我不知道如何获取列表列表中的每个元素:
>>>Cards = [[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C],["JH"]],[["7D"]]]
我想到的是:
for values in cards:
for value in values:
但我想我刚刚得到了有 2 个列表的元素。如何计算卡片中有 3 和 1 的列表?
我正在为我的任务制作一个心脏游戏,但我不知道如何获取列表列表中的每个元素:
>>>Cards = [[["QS","5H","AS"],["2H","8H"],["7C"]],[["9H","5C],["JH"]],[["7D"]]]
我想到的是:
for values in cards:
for value in values:
但我想我刚刚得到了有 2 个列表的元素。如何计算卡片中有 3 和 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
略显晦涩的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 提供更具描述性的名称。
如果您的卡片以一种笨拙的方式嵌套:
>>> 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
您的列表是一个不完整的嵌套列表,因此您可以先使其成为矩形,例如使用此处说明的过程,然后将结果展平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()
使用生成器,可以编写更具可读性的实现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']
使用 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']
这个解决方案对于任何类型的嵌套列表或元组都非常健壮(要添加其他可迭代类型,只需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']
使用来自 Rosetta Code的展平列表,您可以执行以下操作:
>>> 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']
>>>
该解决方案仅展平嵌套列表 - 而不是元组或字符串。
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 太棒了!