2013-05-24 5 views
6

Делаю сердце игры для моего назначения, но я не знаю, как получить каждый элемент в списке список:Как получить каждый элемент в списке списков?

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

и то, что приходит мне на ум:

for values in cards: 
    for value in values: 

Но я думаю, что у меня есть элемент, у которого есть 2 списка. Как рассчитать тот, который имеет 3 и 1 список в карточках?

+3

Я отредактировал ваш код, чтобы добавить дополнительный '' ', поскольку он отсутствует. Почему вы отредактировали это редактирование? –

+0

Вам понадобится рекурсия для достижения того, что вы хотите чистым способом. – Maresh

+0

У вас есть все карты на –

ответ

15

Как это:

>>> 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'] 

Как, Суперначо отметил, пакет 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 
+0

Блестящий! Я не знал, что это существовало. – HennyH

+0

Я не думаю, что они намеревались использовать эту функцию таким образом, но если она работает ... :). – Blubber

+1

Ничего себе !!!! Большое спасибо!! –

4

Если ваши карты вложены в громоздким образом:

>>> 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'] 

Будет recursivly пройти через список и найти все элементы. Вот некоторые timeings я запускать сравнение производительности выбранного 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 
5

Слегка неясное 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'] 

Вы могли бы хотеть дать, Ь, с более описательными именами.

+0

кажется правильным для начальной части. Но 7 и d разделены –

+2

@blubber проблема заключается в том, что они не вложены в одностороннем порядке (что странный способ хранения ваших игровых данных ...) – HennyH

+0

Да, я вижу это сейчас. Ну, тогда вы не можете использовать это, он работает только на регулярно сформированных списках. – Blubber

2

Ваш список неполный вложенный список, так что вы можете сначала сделать его прямоугольным, using the procedure explained here, например, а затем расплющить в результате numpy.ndarray.

«Ifs» ниже также не понадобится, если последний элемент ['7D'] был [['7D']] (тогда будут также работать и другие ответы).

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() 
2

Использование генераторов, можно написать гораздо более читаемую реализацию 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

Используйте 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'] 
2

Это решение является очень надежным для любого вида вложенных списков или кортежей (добавить другие типы Iterable просто добавить больше 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'] 
1

Использование 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'] 
>>> 

Решения только сглаживает вложенные списки - не кортежи или строку.

1
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', 'как', '2H', '8H', '7C', '9H', '5C', 'JH', '7D']

Itertools потрясающий!

Смежные вопросы