Як атрымаць кожны элемент у спісе спісу спісаў?

Раблю сэрца гульні для майго прызначэння, але я не ведаю, як атрымаць кожны элемент у спісе спісу:

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

і тое, што прыходзіць мне ў галаву:

for values in cards:
    for value in values:

Але я думаю, што я толькі што атрымаў элемент, які мае 2 спісу. Як разлічыць той, які мае 3 і 1 спіс у карты?

6
@Erika Sawajiri Гэта не памылка ў апошнім пункце [ «7D»]? Не павінна быць [[ '7D']]?
дададзена аўтар Saullo Castro, крыніца
Я рэдагаваў свой код для дадання ў дадатковы " як гэта адсутнічае. Чаму вы прыбіраеце, што рэдагаванне?
дададзена аўтар Gareth Latty, крыніца
Вы будзеце мець патрэбу ў некаторай рэкурсіўная дамагчыся таго, што вы хочаце ў чыстым выглядзе.
дададзена аўтар Maresh, крыніца
У вас ёсць усе карты на тую ж глыбіню? Тады вам проста трэба пайсці туды.
дададзена аўтар Thomas Fenzl, крыніца
Падобна на тое, у вас ёсць спіс спіс спісаў, але не зачынілі канчатковы кранштэйн.
дададзена аўтар Peter Collingridge, крыніца

9 адказы

Як гэта:

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

Як, Суперначо паказаў, кампілятар пакет з'яўляецца састарэлым. Гэта крыніца 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
15
дададзена
Важна: Састарэлыя пачынаючы з версіі 2.6 :. Пакет кампілятар быў выдалены ў Python 3
дададзена аўтар nacholibre, крыніца
Я не думаю, што яны прызначаны гэтую функцыю для выкарыстання, як гэта, але калі ён працуе ... :).
дададзена аўтар Blubber, крыніца
Праверка тыпу ў цытуемых кодзе даволі непрыгожа і далікатная (ён не будзе апрацоўваць спіс або картэж падкласаў). Лепш адзін будзе калі isinstance (еи, (спіс, картэж)) . Калі вы робіце свой уласны код Звесці ў любым выпадку, вы можаце зрабіць гэта генератар таксама, а не будаваць (магчыма, непатрэбную) спіс.
дададзена аўтар Blckknght, крыніца
Я проста скапіяваў код з compiler.ast.flatten. Вядома, генератар быў бы занадта добра, але гэта залежыць ад канкрэтных патрабаванняў.
дададзена аўтар Hans Then, крыніца
Ці будзе гэта? Я думаю, што гэта будзе толькі перабіраць спісы і картэжы, а не радка.
дададзена аўтар Hans Then, крыніца
Brilliant! Я не ведаю, што гэта было.
дададзена аўтар HennyH, крыніца
Нічога сабе !!!! Вялікі дзякуй!!
дададзена аўтар Erika Sawajiri, крыніца
@Hans але ваша функцыя Flatten аддзеліць ўсе элементы, такія як 7 і C. Тое, што я хачу 7С
дададзена аўтар Erika Sawajiri, крыніца

Трохі невыразнае 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']

Вы можаце даць, Ь і з больш апісальныя імёны.

5
дададзена
@ErikaSawajiri апошні элемент у спісе павінен быць [[ «7D»]], ня гэта памылка друку?
дададзена аўтар Saullo Castro, крыніца
Так, я бачу, што цяпер. Ну вы не можаце выкарыстоўваць гэта тое, ён працуе толькі на рэгулярнай аснове сфармаваных спісаў.
дададзена аўтар Blubber, крыніца
@blubber праблемы яны не з'яўляюцца укладзенымі аднапрацэсарныя фармальна (які з'яўляецца няцотных спосабам для захоўвання гульнявых дадзеных ...)
дададзена аўтар HennyH, крыніца
гэта здаецца правільным для begginning часткі. Але 7 і д аддзеленая
дададзена аўтар Erika Sawajiri, крыніца

Калі вашы карты ўкладзеныя ў грувасткім чынам:

>>> 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
4
дададзена

Ваш спіс няпоўны укладзены спіс, так што вы можаце спачатку зрабіць яго прастакутным, з дапамогай працэдуры, апісанай тут , напрыклад, і затым распляскаць у выніку numpy.ndarray .

У «калі» ніжэй не будзе неабходнасці, а калі апошні элемент [ «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
дададзена

Гэта рашэнне з'яўляецца вельмі надзейным для любога віду ўкладзеных спісаў або картэжаў (дадаць іншыя тыпы Iterable проста дадаць больш або 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']
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
дададзена

Выкарыстанне генератараў, можна напісаць значна больш чытэльным рэалізацыю 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, які дададзены ў выхад з сінтаксіс:

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
дададзена
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 дзіўна!

1
дададзена

Выкарыстанне Звесці спіс ад Rosetta кодэкса вы маглі б зрабіць:

>>> 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
дададзена