207

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

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

我只想从此元组列表中创建一个 id 列表,如下所示:

[1,2]

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

4

14 回答 14

305
>>> a = [(1, u'abc'), (2, u'def')]
>>> [i[0] for i in a]
[1, 2]
于 2012-08-27T13:25:51.693 回答
85

使用 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):以上适用于 Python 2.x,其中zip返回一个列表。

在 Python 3.x 中,zip返回一个迭代器,以下等价于上述内容:

>>> print(list(list(zip(*inpt))[0]))
[1, 2]
于 2015-07-08T15:32:57.773 回答
22

你的意思是这样的吗?

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

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

在这里,我创建了一个平面列表,因为通常这似乎比创建 1 个元素元组的列表更有用。seq[0]但是,您只需用替换即可轻松创建包含 1 个元素的元组列表(seq[0],)

于 2012-08-27T12:39:22.720 回答
15

这是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')]
于 2016-06-28T04:43:28.967 回答
13

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

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

在迭代时,每个元组都被解包,并且它的值被设置为变量idxval

>>> x = (1, 'abc')
>>> idx, val = x
>>> idx
1
>>> val
'abc'
于 2017-04-03T13:12:21.517 回答
12

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

I) 具有 2 个元素的元组的基准测试 在此处输入图像描述

正如您可能期望的那样,通过索引从元组中选择第一个元素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 个或更多元素的元组的基准 在此处输入图像描述

import operator
import random

from simple_benchmark import BenchmarkBuilder

b = BenchmarkBuilder()

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


@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_arguments('Number of tuples')
def argument_provider():
    for exp in range(2, 21):
        size = 2**exp
        yield size, [tuple(random.choice(range(100)) for _
                     in range(random.choice(range(2, 100)))) for _ in range(size)]

from pylab import rcParams
rcParams['figure.figsize'] = 12, 7

r = b.run()
r.plot()
于 2020-02-18T12:25:53.700 回答
8

如果元组是唯一的,那么这可以工作

>>> 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']
>>> 
于 2015-09-29T14:36:20.120 回答
8

从性能上看,在python3.X

  • [i[0] for i 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

于 2017-12-30T23:54:27.747 回答
4

当我跑的时候(如上所述):

>>> 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 测试/运行)

于 2017-03-20T05:46:50.170 回答
2

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

这将是 numpy 中的解决方案:

>>> import numpy as np

>>> a = np.asarray([(1, u'abc'), (2, u'def')])
>>> a[:, 0].astype(int).tolist()
[1, 2]
于 2020-04-06T15:57:11.853 回答
1

您可以解压缩元组并使用列表推导仅获取第一个元素:

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

输出:

[1, 2]

无论元组中有多少元素,这都会起作用:

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

输出:

[1, 2]
于 2020-02-17T18:57:49.977 回答
1

我更喜欢这样压缩:

>>> lst = [(1, u'abc'), (2, u'def')]
>>> new, _ = zip(*lst)
>>> new
(1, 2)
>>> 

或者,如果您不知道有多少额外的值:

>>> new, *_ = zip(*lst)
>>> new
(1, 2)
>>> 
于 2021-11-08T04:07:15.430 回答
1

要获取列表或元组的元素,您可以遍历列表或元组

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

list1 = [a[i][0] for i in range(len(a))]

print(list1)
于 2021-06-16T04:47:34.890 回答
0

这些是元组,而不是集合。你可以这样做:

l1 = [(1, u'abc'), (2, u'def')]
l2 = [(tup[0],) for tup in l1]
l2
>>> [(1,), (2,)]
于 2012-08-27T12:40:14.657 回答