Как преобразовать кортеж кортежей в список в одну строку (pythonic)?
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 ответов
Это работает также:
>>> 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
Смотрите документы по распаковке.
Вы могли бы сделать
>>> tup = (('aa',), ('bb',), ('cc',))
>>> lst = [a[0] for a in tup]
>>> lst
['aa', 'bb', 'cc']
Почему
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
То, что вы делаете, является правильным, но более кратким и может быть лучше
>>> [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 наиболее читаемо
Это работает:
>>> 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']
Сделайте понимание списка следующим образом:
mylist = [ x[0] for x in myoutput ]