17

I have a tuple of tuples and I want to put the first value in each of the tuples into a set. I thought using map() would be a good way of doing this the only thing is I can't find an easy way to access the first element in the tuple. So for example I have the tuple ((1,), (3,)). I'd like to do something like set(map([0], ((1,), (3,)))) (where [0] is accessing the zeroth element) to get a set with 1 and 3 in it. The only way I can figure to do it is to define a function: def first(t): return t[0]. Is there anyway of doing this in one line without having to declare the function?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Ian Burris
  • 6,325
  • 21
  • 59
  • 80

8 Answers8

20

Use a list comprehension:

data = ((1,), (3,))
print([x[0] for x in data])
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Winston Ewert
  • 44,070
  • 10
  • 68
  • 83
  • Using the itemgetter (per Steve Howard's answer) is arguably the better as it was designed specifically for this purpose. – Aaron Torgerson Dec 04 '15 at 15:26
  • @AaronTorgerson, I don't agree. I think this is more readable as it uses python syntax to express it rather then a special object. – Winston Ewert Dec 04 '15 at 19:02
  • Context matters. If I want to sort by a tuple element, using `itemgetter` beats writing a lambda – sehe Jun 29 '18 at 01:09
19

Use operator.itemgetter:

from operator import itemgetter
map(itemgetter(0), ((1,), (3,)))

While the list comprehensions are generally more readable, itemgetter is closest to what you asked for. It's also a bit faster:

>>> from timeit import timeit
>>> setup = 'from operator import itemgetter; lst=( ("a",), ("b",), (1,), (2,))'
>>> timeit('map(itemgetter(0), lst)', setup=setup)
0.13061050399846863
>>> timeit('[i[0] for i in lst]', setup=setup)
0.20302422800159547
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Steve Howard
  • 6,737
  • 1
  • 26
  • 37
  • The two techniques cannot be compared in terms of speed as they serve different purposes. `map` creates a generator, whereas list comprehension creates a list. A fairer comparison would be between list comprehension and `list(map(itemgetter(0), lst))`, which produce similar timing results. But generators are usually preferred if possible. – Arthur R. Mar 23 '23 at 18:11
4
my_set = {x[0] for x in TUPLES}
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
ninjagecko
  • 88,546
  • 24
  • 137
  • 145
3

Python supports the creation of anonymous function using the lambda keyword. This allows you to use a function without formally defining it. Given your example, you'd use the lambda like this:

data = ((1,), (3,))
set(map(lambda x: x[0], data))

This is equivalent to:

def f(x):
    return x[0]

set(map(f, data))

But as other people have said, list comprehensions are preferred over the use of map.

Zach Kelling
  • 52,505
  • 13
  • 109
  • 108
3

Just another way to get it:

set(x for x, in data)
neurino
  • 11,500
  • 2
  • 40
  • 63
2

You can use a set comprehension in Python 2.7 and 3.x:

>>> t = ((1,), (3,))
>>> s = {x[0] for x in t}
>>> s
set([1, 3])

or in Python < 2.7:

>>> s = set([x[0] for x in t])
>>> s
set([1, 3])
Gregg
  • 3,236
  • 20
  • 15
2
data = ((1,), (3,))
s = set(zip(*data)[0])

If there are more items in your tuples you might save some memory and time using izip and islice.

Yann Vernier
  • 15,414
  • 2
  • 28
  • 26
1

Go with @Winston. List comprehensions are great. If you really want to use map, use a lambda as previously suggested, or the logically equivalent...

from operator import itemgetter
data = ((1,), (3,))
map(itemgetter(0), data)

This is just for info; You should use the list comp

Rob Cowie
  • 22,259
  • 6
  • 62
  • 56