可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
query = 'select mydata from mytable'
cursor.execute(query)
myoutput = cursor.fetchall()
print myoutput
(('aa',), ('bb',), ('cc',))
Why is it (cursor.fetchall) returning a tuple of tuples instead of a tuple since my query is asking for only one column of data?
What is the best way of converting it to ['aa', 'bb', 'cc']
?
I can do something like this :
mylist = []
myoutput = list(myoutput)
for each in myoutput:
mylist.append(each[0])
I am sure this isn't the best way of doing it. Please enlighten me!
回答1:
This works as well:
>>> tu = (('aa',), ('bb',), ('cc',))
>>> import itertools
>>> list(itertools.chain(*tu))
['aa', 'bb', 'cc']
Edit Could you please comment on the cost tradeoff? (for loop and itertools)
Itertools is significantly faster:
>>> 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
Edit 2 Could you pl explain itertools.chain(*)
That *
unpacks the sequence into positional arguments, in this case a nested tuple of tuples.
Example:
>>> 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',)
Another example:
>>> f('abcde')
len args: 1
abcde
>>> f(*'abcde')
len args: 5
a
b
c
d
e
See the documents on unpacking.
回答2:
You could do
>>> tup = (('aa',), ('bb',), ('cc',))
>>> lst = [a[0] for a in tup]
>>> lst
['aa', 'bb', 'cc']
回答3:
Why is cursor.fetchall()
returning a tuple of tuples instead of a tuple since my query is asking for only one column of data?
The outer tuple is the complete result; each inner tuple represents one record in that result; because you asked for only one field, each inner tuple has only one element.
What is the best way of converting it to ['aa', 'bb', 'cc'] ?
There are several ways, and which is 'best' depends on what you are doing...
Simple list comprehension:
mylist = [each[0] for each in myoutput]
Simple generator (saves on memory usage):
mygen = (each[0] for each in myoutput)
for result in mygen:
print result
If you just need to process the items in myoutput
, you could also do
for each, in myoutput:
print each
If you have profiled your code and discovered that this is a bottleneck, then you can go for less readable but faster:
import itertools
mylist = list(itertools.chain(*myoutput))
or, again if you just need to process it:
import itertools
for result in itertools.chain(*myoutput):
print result
回答4:
What you are doing is correct but more concise and may be better performing could be
>>> [item for item, in (('aa',), ('bb',), ('cc',)) ]
['aa', 'bb', 'cc']
or if you hate for
keyword, you can use map
>>> map(lambda a:a[0], (('aa',), ('bb',), ('cc',)) )
['aa', 'bb', 'cc']
and here is another way
>>> reduce(lambda a, b:a+b, (('aa',), ('bb',), ('cc',)) )
('aa', 'bb', 'cc')
though IMO list comprehension is most readable
回答5:
This works:
>>> tups=(('aa',), ('bb',), ('cc',))
>>> list(*(zip(*tups)))
['aa', 'bb', 'cc']
Explanation:
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.
You could also do:
>>> list(zip(*tups)[0])
['aa', 'bb', 'cc']
回答6:
Do a list comprehension like this:
mylist = [ x[0] for x in myoutput ]