Python 如何获取元组列表中的第一个元素?

Python 如何获取元组列表中的第一个元素?,python,list,Python,List,我有一个如下列表,其中第一个元素是id,另一个是字符串: [(1, u'abc'), (2, u'def')] 我只想从这个元组列表中创建一个ID列表,如下所示: [1,2] 我将在中使用这个列表,所以它需要是一个整数值列表。你的意思是这样的吗 new_list = [ seq[0] for seq in yourlist ] 实际上,您拥有的是一个元组对象列表,而不是一个集合列表(正如您最初的问题所暗示的那样)。如果它实际上是一个集合列表,那么就没有第一个元素,因为集合没有顺序 在这里,

我有一个如下列表,其中第一个元素是id,另一个是字符串:

[(1, u'abc'), (2, u'def')]
我只想从这个元组列表中创建一个ID列表,如下所示:

[1,2]

我将在中使用这个列表,所以它需要是一个整数值列表。

你的意思是这样的吗

new_list = [ seq[0] for seq in yourlist ]
实际上,您拥有的是一个
元组
对象列表,而不是一个集合列表(正如您最初的问题所暗示的那样)。如果它实际上是一个集合列表,那么就没有第一个元素,因为集合没有顺序


在这里,我创建了一个平面列表,因为它通常比创建一个由1个元素元组组成的列表更有用。但是,只需将
seq[0]
替换为
(seq[0],)

即可轻松创建一个1元素元组列表,这些元组是元组,而不是集合。您可以这样做:

l1 = [(1, u'abc'), (2, u'def')]
l2 = [(tup[0],) for tup in l1]
l2
>>> [(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]
编辑(@BradSolomon): 以上内容适用于Python2.x,其中
zip
返回一个列表

在Python3.x中,
zip
返回一个迭代器,以下内容与上述内容等效:

>>> print(list(list(zip(*inpt))[0]))
[1, 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']
>>> 
这就是为什么

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')]
当我跑步时(如上所述):

而不是返回:

[1, 2]
我收到了这个作为回报:

<map at 0xb387eb8>
使用此建议成功返回列表。也就是说,我对这个解决方案很满意,谢谢。(使用Spyder、iPython控制台、Python v3.6进行测试/运行)

您可以使用“元组解包”:

在迭代时,每个元组被解包,其值被设置为变量
idx
val

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

从性能的角度来看,在python3.X中

  • [i[0]表示a中的i]
    列表(zip(*a))[0]
    是等效的
  • 它们比列表(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

您可以使用列表理解来创建元组并仅获取第一个元素:

l = [(1, u'abc'), (2, u'def')]
[f for f, *_ in l]
输出:

[1, 2]
[1, 2]
>>> import numpy as np

>>> a = np.asarray([(1, u'abc'), (2, u'def')])
>>> a[:, 0].astype(int).tolist()
[1, 2]
无论元组中有多少个元素,这都会起作用:

l = [(1, u'abc'), (2, u'def', 2, 4, 5, 6, 7)]
[f for f, *_ in l]
输出:

[1, 2]
[1, 2]
>>> import numpy as np

>>> a = np.asarray([(1, u'abc'), (2, u'def')])
>>> a[:, 0].astype(int).tolist()
[1, 2]

我认为比较不同方法的运行时可能有用,所以我做了一个基准测试(使用库)

I)具有两个元素元组的基准测试

正如您所期望的那样,通过索引从元组中选择第一个元素
0
显示出最快的解决方案,它与解包解决方案非常接近,只需要2个值

import operator
import random

from simple_benchmark import BenchmarkBuilder

b = BenchmarkBuilder()



@b.add_function()
def rakesh_by_index(l):
    return [i[0] for i in l]


@b.add_function()
def wayneSan_zip(l):
    return list(list(zip(*l))[0])


@b.add_function()
def bcattle_itemgetter(l):
     return list(map(operator.itemgetter(0), l))


@b.add_function()
def ssoler_upacking(l):
    return [idx for idx, val in l]

@b.add_function()
def kederrack_unpacking(l):
    return [f for f, *_ in l]



@b.add_arguments('Number of tuples')
def argument_provider():
    for exp in range(2, 21):
        size = 2**exp
        yield size, [(random.choice(range(100)), random.choice(range(100))) for _ in range(size)]


r = b.run()
r.plot()
II)具有包含2个或更多元素的元组的基准测试


我想知道为什么没有人建议使用numpy,但现在检查后我明白了。对于混合类型数组,它可能不是最好的

这将是numpy的解决方案:

[1, 2]
[1, 2]
>>> import numpy as np

>>> a = np.asarray([(1, u'abc'), (2, u'def')])
>>> a[:, 0].astype(int).tolist()
[1, 2]

我试过了。它给出了这样一个错误:
int()参数必须是字符串或数字,而不是'QuerySet'
@wasimbhalli--
int()
在我的解决方案中不存在,因此您看到的异常必须稍后出现在代码中。我已经更新了问题,我需要稍后在
\u in
中使用此列表来过滤数据
\u in
中是什么?--根据您给出的示例输入,这将创建一个整数列表。但是,如果元组列表不是以整数开头的,那么就不会得到整数,您需要通过
int
将它们变成整数,或者尝试找出第一个元素不能转换为整数的原因。如果type(seq[0])==int,
new_list=[seq[0]是否表示列表中的seq
work?不是真正要问的问题这需要单独导入吗?@JuliandotNut不,这是一个内置函数。(在Python2.x中)为什么第二次强制转换到
list
是必要的?这将失去顺序。但是,它可能适用于
ordereddict
。如果两个或多个元组具有相同的第一个元素,则解决方案将不起作用