Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
比较Python中连续元组列表的第一个元素_Python_List_Python 2.7_Compare_Append - Fatal编程技术网

比较Python中连续元组列表的第一个元素

比较Python中连续元组列表的第一个元素,python,list,python-2.7,compare,append,Python,List,Python 2.7,Compare,Append,我有一个元组列表,每个元组包含两个元素。少数子列表的第一个元素是常见的。我想比较这些子列表的第一个元素,并将第二个元素附加到一个列表中。以下是我的清单: myList=[(1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)] 我想从中列出一个列表,如下所示:` NewList=[(2,3,4,5),(6,7,8),(9,10)] 我希望有什么有效的方法 您可以使用按每个元组的第一个子元素对元素进行分组: myList=[(1,2),(1

我有一个元组列表,每个元组包含两个元素。少数子列表的第一个元素是常见的。我想比较这些子列表的第一个元素,并将第二个元素附加到一个列表中。以下是我的清单:

myList=[(1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)]
我想从中列出一个列表,如下所示:`

NewList=[(2,3,4,5),(6,7,8),(9,10)]
我希望有什么有效的方法

您可以使用按每个元组的第一个子元素对元素进行分组:

myList=[(1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)]

from collections import OrderedDict

od  = OrderedDict()

for a,b in myList:
    od.setdefault(a,[]).append(b)

print(list(od.values()))
[[2, 3, 4, 5], [6, 7, 8], [9, 10]]
如果您确实想要元组:

print(list(map(tuple,od.values())))
[(2, 3, 4, 5), (6, 7, 8), (9, 10)]
如果您不关心元素出现的顺序,只想以最有效的方式进行分组,您可以使用:

最后,如果您的数据按照输入示例的顺序排列(即排序),您可以简单地使用从每个元组中按第一个子元素分组,并从分组的元组中提取第二个元素:

from itertools import groupby
from operator import itemgetter
print([tuple(t[1] for t in v) for k,v in groupby(myList,key=itemgetter(0))])
输出:

[(2, 3, 4, 5), (6, 7, 8), (9, 10)]
同样,只有当您的数据至少按第一个元素排序时,groupby才会起作用

合理规模列表上的一些时间安排:

In [33]: myList = [(randint(1,10000),randint(1,10000)) for _ in range(100000)]

In [34]: myList.sort()

In [35]: timeit ([tuple(t[1] for t in v) for k,v in groupby(myList,key=itemgetter(0))])
10 loops, best of 3: 44.5 ms per loop

In [36]: %%timeit                                                               od = defaultdict(list)
for a,b in myList:
    od[a].append(b)
   ....: 
10 loops, best of 3: 33.8 ms per loop

In [37]: %%timeit
dictionary = OrderedDict()
for x, y in myList:
     if x not in dictionary:
        dictionary[x] = [] # new empty list
    dictionary[x].append(y)
   ....: 
10 loops, best of 3: 63.3 ms per loop

In [38]: %%timeit   
od = OrderedDict()
for a,b in myList:
    od.setdefault(a,[]).append(b)
   ....: 
10 loops, best of 3: 80.3 ms per loop
如果顺序很重要,并且数据已经排序,那么使用groupby,如果需要将所有元素映射到defaultdict中的tuple,那么它将更接近defaultdict方法


如果数据没有排序,或者您不关心任何顺序,那么您将找不到比使用defaultdict方法更快的分组方法。

这感觉像是字典的任务(如果您还不知道字典,请在python.org上查找它们)。这是一个非常详细的示例,因此我不会在日常编码中这样写,但最好是详细而不是不清楚:

dictionary = collections.OrderedDict()
for x, y in myList:
    if not dictionary.has_key(x):
        dictionary[x] = [] # new empty list
    # append y to that list
    dictionary[x].append(y)

考虑到这一点,最有效的方法可能是这一行(假设
dictionary
是一个空的
dict
,即
dictionary={}
dictionary=OrderedDict()
类似于:

我不是说这是最容易阅读的方法,但我喜欢:)

编辑Ha!基准测试证明我错了;
setdefault
方法比
方法(如果不是字典)慢。has_键(x):dictionary[x]=[]
方法:

>>> timeit.timeit("for x,y in myList:\n    if not dictionary.has_key(x):\n        dictionary[x]=[]\n    dictionary[x].append(y)", "from collections import OrderedDict\nmyList=[(1,2),(1,3),(
1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)]\ndictionary=OrderedDict()")
2.2573769092559814
>>> timeit.timeit("for x,y in myList: dictionary.setdefault(x,[]).append(y)", "from collections import OrderedDict\nmyList=[(1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)]\ndictiona
ry=OrderedDict()")
3.3534231185913086
当然,Padraic仍然是正确的:他的
defaultdict
方法在我的机器上只使用了0.82秒,因此速度快了3倍


此外,正如Padraic所指出的:
dict.has_key(x)
已被弃用,应该在dict中使用
x;但是,我无法测量速度差。

以下各项应能正常工作:

import itertools

myList = [(1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)]
print [tuple(x[1] for x in g) for k, g in itertools.groupby(myList, key=lambda x: x[0])]
其中显示:

[(2, 3, 4, 5), (6, 7, 8), (9, 10)]

如果子元组的第一个元素不常见怎么办?你想要一个单一元素的元组吗?那不是一个列表列表,而是一个元组列表;这对你的问题没有影响,但你还是应该意识到不同之处谢谢你的更正。谢谢Padraic,谢谢你的代码。这帮助我解决了我幼稚的问题。同意,这可能是最有效的approach@PadraicCunningham我收回我的观点,这可能是最有效的方法;请看。@MarcusMüller,你的方法没有一个符合顺序,如果顺序与我无关,我的defaultdict方法将比你的两个答案中的任何一个更有效。因为我没有时间,所以在groupby上不确定it@PadraicCunningham很好,但是使用
orderedict()
而不是
{}
可以解决这个问题,所以我在更新中参考了您的答案。当然,假设“有序”并不意味着“按照第一个元组成员第一次出现的顺序”,而是“按数字排序”。
考虑到这一点后,您是否也进行了测量?顺便说一句:你为什么要“复制”一个答案?@Wolf:我指的是,不是复制:)是的,但是说这可能是最有效的方法,一句评论就足够了。这是一个自给自足的答案。我不同意你对那件事的批评。还有,基准!它在python2中被弃用,
中的
也比has_keySorry快,完全一致。可能需要提到的是,数据必须按排序顺序排列,至少要到第一个元素goThanks Marcus的建议为止。我想了解Python的不同模块,这将使我能够流利地使用Python。如果你有更好的建议,请告诉我。
import itertools

myList = [(1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(2,8),(3,9),(3,10)]
print [tuple(x[1] for x in g) for k, g in itertools.groupby(myList, key=lambda x: x[0])]
[(2, 3, 4, 5), (6, 7, 8), (9, 10)]