3

I'm getting an iterable of tuples as a result from a sqlite3 select statement, and I want to give this iterable to a function that expects a string iterable. How can I override the next function to give the first index of the tuple? Or to be more precise, what is the right pythonic way of doing this?

>>> res = conn.execute(query,(font,))
>>> train_counts = count_vect.fit_transform(res)

AttributeError: 'tuple' object has no attribute 'lower'

EDIT:

Since mapping involves iterating over the entire list it takes twice as much time as just constructing a generator as Niklas offered.

first = """
l = list()
for i in xrange(10):
    l.append((i,))

for j in (i[0] for i in l):
    j
"""


second = """
l = list()
for i in xrange(10):
    l.append((i,))

convert_to_string = lambda t: "%d" % t
strings = map(convert_to_string, l)

for j in strings:
    j
"""

third = """
l = list()
for i in xrange(10):
    l.append((i,))

strings = [t[0] for t in l]

for j in strings:
    j
"""

print "Niklas B. %f" % timeit.Timer(first).timeit()
print "Richard Fearn %f" % timeit.Timer(second).timeit()
print "Richard Fearn #2 %f" % timeit.Timer(third).timeit()

>>>
Niklas B. 4.744230
Richard Fearn 12.016272
Richard Fearn #2 12.041094
2
  • @NiklasB. please post your comment as answer and I'll accept it Commented May 12, 2012 at 13:06
  • Just to be fair: map in Python 3 is just as lazy as a generator expression :) Commented May 12, 2012 at 13:14

2 Answers 2

4

You need to write a function that will convert each tuple into a string; then you can use map to convert the sequence of tuples into a sequence of strings.

For example:

# assume each tuple contains 3 integers
res = ((1,2,3), (4,5,6))

# converts a 3-integer tuple (x, y, z) to a string with the format "x-y-z"
convert_to_string = lambda t: "%d-%d-%d" % t

# convert each tuple to a string
strings = map(convert_to_string, res)

# call the same function as before, but with a sequence of strings
train_counts = count_vect.fit_transform(strings)

If you want the first item from each tuple, your function could be:

convert_to_string = lambda t: t[0]

(assuming that first element is already a string).

Actually in that case you could avoid the lambda altogether and use a list comprehension:

strings = [t[0] for t in res]
Sign up to request clarification or add additional context in comments.

1 Comment

You could use a list comprehension for your initial map/lambda bit too: strings = ["%d-%d-%d" % (x,y,z) for x,y,z in res]
2

The simple solution would be to use a generator expression:

count_vect.fit_transform(t[0] for t in res)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.