Как получить первый элемент в списке кортежей?

116

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

[(1, u'abc'), (2, u'def')]

Я хочу создать список идентификаторов только из этого списка кортежей, как показано ниже:

[1,2]

Я буду использовать этот список в __in поэтому он должен быть списком целочисленных значений.

Теги:
list

9 ответов

146
Лучший ответ
>>> a = [(1, u'abc'), (2, u'def')]
>>> [i[0] for i in a]
[1, 2]
  • 1
    нужно преобразование int?
  • 0
    Нет, не совсем. Даже если вам нужно принудительно ввести тип для прохождения проверки типов, было бы лучше ввести a виде List[Tuple[int, str]] чем преобразовать в int. Преобразование будет необходимо только в том случае, если вы не можете гарантировать, что первым элементом каждого кортежа является int, и в этом случае вы можете использовать его как форму проверки.
48

Используйте функцию zip для разделения элементов:

>>> inpt = [(1, u'abc'), (2, u'def')]
>>> unzipped = zip(*inpt)
>>> print unzipped
[(1, 2), (u'abc', u'def')]
>>> print list(unzipped[0])
[1, 2]

Edit (@BradSolomon): вышеописанное работает для Python 2.x, где zip возвращает список.

В Python 3.x zip возвращает итератор, а следующее эквивалентно приведенному выше:

>>> print(list(list(zip(*inpt))[0]))
[1, 2]
  • 0
    для этого нужен отдельный импорт?
  • 1
    @JuliandotNut Нет, это встроенная функция. (в Python 2.x)
18

Вы имеете в виду что-то вроде этого?

new_list = [ seq[0] for seq in yourlist ]

На самом деле у вас есть список объектов tuple, а не список наборов (как предполагал ваш оригинальный вопрос). Если на самом деле это список наборов, то нет первого элемента, потому что наборы не имеют порядка.

Здесь я создал плоский список, потому что обычно это кажется более полезным, чем создание списка из 1 элемента кортежей. Однако вы можете легко создать список из 1 элемента кортежей, просто заменив seq[0] на (seq[0],).

  • 0
    Я попробовал это. Это дает такую ошибку: int() argument must be a string or a number, not 'QuerySet'
  • 4
    @wasimbhalli - int() нигде в моем решении, поэтому исключение, которое вы видите, должно появиться позже в коде.
Показать ещё 6 комментариев
6

Вы можете использовать "распаковку кортежа":

>>> my_list = [(1, u'abc'), (2, u'def')]
>>> my_ids = [idx for idx, val in my_list]
>>> my_ids
[1, 2]

В момент итерации каждый кортеж распаковывается, а его значения устанавливаются на переменные idx и val.

>>> x = (1, u'abc')
>>> idx, val = x
>>> idx
1
>>> val
u'abc'
5

Для этого и нужен operator.itemgetter.

>>> a = [(1, u'abc'), (2, u'def')]
>>> import operator
>>> b = map(operator.itemgetter(0), a)
>>> b
[1, 2]

Оператор itemgetter возвращает функцию, которая возвращает индекс указанного вами элемента. Это точно так же, как написание

>>> b = map(lambda x: x[0], a)

Но я считаю, что itemgetter является более четким и более явным.

Это удобно для создания компактных операторов сортировки. Например,

>>> c = sorted(a, key=operator.itemgetter(0), reverse=True)
>>> c
[(2, u'def'), (1, u'abc')]
4

С точки зрения производительности, в python3.X

  • [i[0] for я in a] и list(zip(*a))[0] эквивалентны
  • они быстрее, чем list(map(operator.itemgetter(0), a))

Код

import timeit


iterations = 100000
init_time = timeit.timeit('''a = [(i, u'abc') for i in range(1000)]''', number=iterations)/iterations
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]\nb = [i[0] for i in a]''', number=iterations)/iterations - init_time)
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]\nb = list(zip(*a))[0]''', number=iterations)/iterations - init_time)

выход

3.491014136001468e-05

3.422205176000717e-05

2

если кортежи уникальны, тогда это может работать

>>> a = [(1, u'abc'), (2, u'def')]
>>> a
[(1, u'abc'), (2, u'def')]
>>> dict(a).keys()
[1, 2]
>>> dict(a).values()
[u'abc', u'def']
>>> 
  • 3
    Это потеряет порядок. Это может работать с ordereddict , хотя.
1

когда я бежал (как было предложено выше):

>>> a = [(1, u'abc'), (2, u'def')]
>>> import operator
>>> b = map(operator.itemgetter(0), a)
>>> b

вместо возврата:

[1, 2]

Я получил это как возвращение:

<map at 0xb387eb8>

Я нашел, что мне пришлось использовать list():

>>> b = list(map(operator.itemgetter(0), a))

чтобы успешно вернуть список, используя это предложение. Тем не менее, я доволен этим решением, спасибо. (протестировано/запущено с помощью Spyder, консоли iPython, Python v3.6)

0

Это кортежи, а не набор. Вы можете сделать это:

l1 = [(1, u'abc'), (2, u'def')]
l2 = [(tup[0],) for tup in l1]
l2
>>> [(1,), (2,)]
  • 1
    Не совсем то, что просят

Ещё вопросы

Сообщество Overcoder
Наверх
Меню