Как преобразовать кортеж кортежей в список в одну строку (pythonic)? - PullRequest
5 голосов
/ 17 ноября 2011
query = 'select mydata from mytable'
cursor.execute(query)
myoutput = cursor.fetchall() 
print myoutput

(('aa',), ('bb',), ('cc',))

Почему он (cursor.fetchall) возвращает кортеж кортежей вместо кортежа, поскольку мой запрос запрашивает только один столбец данных?

Как лучше всего преобразовать его в['aa', 'bb', 'cc']?

Я могу сделать что-то вроде этого:

mylist = []
myoutput = list(myoutput)
for each in myoutput:
   mylist.append(each[0])

Я уверен, что это не лучший способ сделать это.Пожалуйста, просветите меня!

Ответы [ 6 ]

7 голосов
/ 17 ноября 2011

Это также работает:

>>> tu = (('aa',), ('bb',), ('cc',))
>>> import itertools
>>> list(itertools.chain(*tu))
['aa', 'bb', 'cc']

Редактировать Could you please comment on the cost tradeoff? (for loop and itertools)

Itertools значительно быстрее:

>>> t = timeit.Timer(stmt="itertools.chain(*(('aa',), ('bb',), ('cc',)))")
>>> print t.timeit()
0.341422080994
>>> t = timeit.Timer(stmt="[a[0] for a in (('aa',), ('bb',), ('cc',))]")
>>> print t.timeit()
0.575773954391

Редактировать 2 Could you pl explain itertools.chain(*)

То, что * распаковывает последовательность в позиционные аргументы, в данном случае это вложенный кортеж кортежей.

Пример:

>>> def f(*args):
...    print "len args:",len(args)
...    for a in args:
...       print a
... 
>>> tu = (('aa',), ('bb',), ('cc',))
>>> f(tu)
len args: 1
(('aa',), ('bb',), ('cc',))
>>> f(*tu)
len args: 3
('aa',)
('bb',)
('cc',)

Другой пример:

>>> f('abcde')
len args: 1
abcde
>>> f(*'abcde')
len args: 5
a
b
c
d
e

См. документы по распаковке .

4 голосов
/ 17 ноября 2011

Вы могли бы сделать

>>> tup = (('aa',), ('bb',), ('cc',))
>>> lst = [a[0] for a in tup]
>>> lst
['aa', 'bb', 'cc']
2 голосов
/ 18 ноября 2011

Почему cursor.fetchall() возвращает кортеж кортежей вместо кортежа, поскольку мой запрос запрашивает только один столбец данных?

Внешний кортеж - это полный результат; каждый внутренний кортеж представляет одну запись в этом результате; поскольку вы запрашивали только одно поле, у каждого внутреннего кортежа есть только один элемент.

Как лучше всего преобразовать его в ['aa', 'bb', 'cc']?

Есть несколько способов, и «лучший» зависит от того, что вы делаете ...

Простое понимание списка:

mylist = [each[0] for each in myoutput]

Простой генератор (экономит использование памяти):

mygen = (each[0] for each in myoutput)
for result in mygen:
    print result

Если вам просто нужно обработать элементы в myoutput, вы также можете сделать

for each, in myoutput:
    print each

Если вы профилировали свой код и обнаружили, что это узкое место, то вы можете пойти на менее читабельное, но более быстрое:

import itertools
mylist = list(itertools.chain(*myoutput))

или, опять же, если вам просто нужно обработать его:

import itertools
for result in itertools.chain(*myoutput):
    print result
2 голосов
/ 17 ноября 2011

То, что вы делаете, правильно, но более кратко и может быть более эффективным, может быть

>>> [item for item, in (('aa',), ('bb',), ('cc',)) ]
['aa', 'bb', 'cc']

или если вы ненавидите ключевое слово for, вы можете использовать карту

>>> map(lambda a:a[0], (('aa',), ('bb',), ('cc',)) )
['aa', 'bb', 'cc']

и вот еще один способ

>>> reduce(lambda a, b:a+b, (('aa',), ('bb',), ('cc',)) )
('aa', 'bb', 'cc')

, хотя понимание списка IMO наиболее читаемо

1 голос
/ 13 сентября 2012

Это работает:

>>> tups=(('aa',), ('bb',), ('cc',))
>>> list(*(zip(*tups)))
['aa', 'bb', 'cc']

Объяснение:

1) *tups unpacks the nested tuples  ('aa'),('bb'),('cc')
2) zip produces a list of a single tuple with all the elements: [('aa','bb','cc')]
3) * unpacks that  into  'aa', 'bb', 'cc'
4) creates a list from that unpacking.

Вы также можете сделать:

>>> list(zip(*tups)[0])
['aa', 'bb', 'cc']
0 голосов
/ 17 ноября 2011

Сделайте понимание списка следующим образом:

mylist = [ x[0] for x in myoutput ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...