У меня есть список, как показано ниже, где первый элемент является идентификатором, а другой является строкой:
[(1, u'abc'), (2, u'def')]
Я хочу создать список идентификаторов только из этого списка кортежей, как показано ниже:
[1,2]
Я буду использовать этот список в __in
поэтому он должен быть списком целочисленных значений.
>>> a = [(1, u'abc'), (2, u'def')]
>>> [i[0] for i in a]
[1, 2]
Используйте функцию 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]
Вы имеете в виду что-то вроде этого?
new_list = [ seq[0] for seq in yourlist ]
На самом деле у вас есть список объектов tuple
, а не список наборов (как предполагал ваш оригинальный вопрос). Если на самом деле это список наборов, то нет первого элемента, потому что наборы не имеют порядка.
Здесь я создал плоский список, потому что обычно это кажется более полезным, чем создание списка из 1 элемента кортежей. Однако вы можете легко создать список из 1 элемента кортежей, просто заменив seq[0]
на (seq[0],)
.
int() argument must be a string or a number, not 'QuerySet'
int()
нигде в моем решении, поэтому исключение, которое вы видите, должно появиться позже в коде.
Вы можете использовать "распаковку кортежа":
>>> 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'
Для этого и нужен 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')]
С точки зрения производительности, в 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
если кортежи уникальны, тогда это может работать
>>> 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']
>>>
ordereddict
, хотя.
когда я бежал (как было предложено выше):
>>> 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)
Это кортежи, а не набор. Вы можете сделать это:
l1 = [(1, u'abc'), (2, u'def')]
l2 = [(tup[0],) for tup in l1]
l2
>>> [(1,), (2,)]
a
видеList[Tuple[int, str]]
чем преобразовать в int. Преобразование будет необходимо только в том случае, если вы не можете гарантировать, что первым элементом каждого кортежа является int, и в этом случае вы можете использовать его как форму проверки.