我有一个像下面这样的列表,其中第一个元素是id,另一个是字符串:
[(1, u'abc'), (2, u'def')]
我只想从此元组列表创建ID列表,如下所示:
[1,2]
我将使用此列表,__in
因此它必须是整数值的列表。
我有一个像下面这样的列表,其中第一个元素是id,另一个是字符串:
[(1, u'abc'), (2, u'def')]
我只想从此元组列表创建ID列表,如下所示:
[1,2]
我将使用此列表,__in
因此它必须是整数值的列表。
Answers:
使用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]
你的意思是这样吗?
new_list = [ seq[0] for seq in yourlist ]
您实际拥有的是tuple
对象列表,而不是集合列表(正如您的原始问题所暗示的)。如果实际上是集合的列表,则没有第一个元素,因为集合没有顺序。
在这里,我创建了一个平面列表,因为通常来说,这似乎比创建1个元素元组的列表更有用。但是,只需替换seq[0]
为,就可以轻松创建1个元素元组的列表(seq[0],)
。
int() argument must be a string or a number, not 'QuerySet'
int()
在我的解决方案中不存在,因此您看到的异常必须稍后在代码中出现。
__in
来过滤数据
__in
?-根据您提供的示例输入,这将创建一个整数列表。但是,如果元组列表不是以整数开头,那么您将不会获得整数,并且需要通过来使它们成为整数int
,或者尝试弄清楚为什么第一个元素不能转换为整数。
new_list = [ seq[0] for seq in yourlist if type(seq[0]) == int]
工作吗?
这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 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
当我跑步时(如上所述):
>>> 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测试/运行)
我当时认为比较不同方法的运行时可能很有用,所以我做了一个基准测试(使用simple_benchmark库)
您可能希望通过索引从元组中选择第一个元素0
,这是最快的解决方案,非常接近拆包解决方案,因为恰好需要两个值
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()
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()