Python 根据第一个常用项将子列表排序为新的子列表
我有大量两个成员的子列表,它们是名为Python 根据第一个常用项将子列表排序为新的子列表,python,list,sorting,Python,List,Sorting,我有大量两个成员的子列表,它们是名为mylist的列表的成员: mylist = [['AB001', 22100], ['AB001', 32935], ['XC013', 99834], ['VD126', 18884], ['AB001', 34439], ['XC013', 86701]] 我想根据子列表是否包含与第一项相同的字符串,将mylist排序到新的子列表中。例如,这就是我希望代
mylist
的列表的成员:
mylist = [['AB001', 22100],
['AB001', 32935],
['XC013', 99834],
['VD126', 18884],
['AB001', 34439],
['XC013', 86701]]
我想根据子列表是否包含与第一项相同的字符串,将mylist
排序到新的子列表中。例如,这就是我希望代码输出的内容:
newlist = [['AB001', 22100], ['AB001', 32935], ['AB001', 34439]],
[['XC013', 99834], ['XC013', 86701]],
[['VD126', 18884]]
下面是我如何编写代码的:
mylist = sorted(mylist)
newlist = []
for sublist in mylist:
id = sublist[0]
if id == next.id:
newlist.append(id)
print newlist
我还试图了解
itertools.groupby()
是否是解决此问题的正确工具。有人能帮我解决这个问题吗 你说得对,这是一份适合以下人员的工作:
这将为您提供一个列表列表,按子列表中的第一项分组
[[['AB001', 4439], ['AB001', 22100], ['AB001', 32935]],
[['VD126', 18884]],
[['XC013', 86701], ['XC013', 99834]]]
itertools.groupby
解决方案将产生O(n log n)成本,因为必须首先对输入进行排序。您可以使用列表的defaultdict
来保证O(n)解决方案:
from collections import defaultdict
dd = defaultdict(list)
for item in mylist:
dd[item[0]].append(item)
res = list(dd.values())
print(res)
[[['AB001', 22100], ['AB001', 32935], ['AB001', 34439]],
[['XC013', 99834], ['XC013', 86701]],
[['VD126', 18884]]]
不导入任何包:
- 构建一个字典,然后将值添加到列表中
- 用于确定某个键是否存在,如果该键不存在,则返回某个指定值,
None
- 默认为
,因此此方法不会引发错误。None
- 如果
是字典中的值,则更改None
返回的默认值。.get
test.get(t[0],'something here')
- 如果
- 用于确定某个键是否存在,如果该键不存在,则返回某个指定值,
- 因为:基于公共首项的子列表。
- 添加索引0作为
,然后添加键
,列表
,作为t
值dict
- 添加索引0作为
test=dict()
对于mylist中的t:
如果test.get(t[0])==无:
测试[t[0]]=[t]
其他:
测试[t[0]]。追加(t)
final=列表(test.values())
#在中打印最终结果
[AB001',22100],[AB001',32935],[AB001',34439],
[XC013',99834],[XC013',86701],
[VD126',18884]]
解决此问题有多种选择:
def regroup_by_di(items, key=None):
result = {}
callable_key = callable(key)
for item in items:
key_value = key(item) if callable_key else item
if key_value not in result:
result[key_value] = []
result[key_value].append(item)
return result
这些可分为两类:
按di()重新分组()
,按dd()重新分组()
,按sd()重新分组()
)regroupbyuit()
,regroupbyugb()
)O(n)
计算复杂度,而第二类方法具有O(n logn)
所有建议的方法都需要指定一个键
。
对于OP的问题,操作符.itemgetter(0)
或lambda x:x[0]
可以工作。此外,要获得OP所需的结果,只能获得列表(dict.values())
,例如:
from operator import itemgetter
mylist = [['AB001', 22100],
['AB001', 32935],
['XC013', 99834],
['VD126', 18884],
['AB001', 4439],
['XC013', 86701]]
print(list(regroup_by_di(mylist, key=itemgetter(0)).values()))
# [[['AB001', 22100], ['AB001', 32935], ['AB001', 4439]], [['XC013', 99834], ['XC013', 86701]], [['VD126', 18884]]]
所有基于
dict
的(一级)解决方案的计时速度更快,而所有基于groupby
的(二级)解决方案的计时速度较慢。
在基于dict的解决方案中,它们的性能将略微取决于“碰撞率”,这与新项目创建新对象的次数成正比。
对于较高的碰撞率,regroup\u by_di()
可能是最快的,而对于较低的碰撞率,regroup\u by_dd()
可能是最快的
基准如下:
- 0.1%碰撞率(每组约1000个元件)
- 10%碰撞率(每组约10个元件)
- 50%碰撞率(每组约2个元件)
- 100%碰撞率(每组约1个元件)
(更多详细信息可用。)若要保存导入,您是否可以使用lambda而不是itemgetter?是的,但速度较慢,这就是itemgetter
的作用。实际上,您必须按分组所依据的键进行排序,因此,sorted(mylist)
应替换为sorted(mylist,key=itemgetter(0)
@norok2这取决于你是否关心组中值的顺序。如果你不关心,你是对的,你可以再次使用itemgetter
。但是这个细节对答案的要点并不重要;重要的部分是groupby
和itemgetter
。在这种情况下,de>错误排序工作正常。这不是赌注组中值的顺序,而是组本身。sorted(mylist)
在这里工作正常,因为sorted(mylist,key=itemgetter(0))
将导致相同的分组(对组中值的顺序进行模化)在这种情况下,但它通常是不正确的,例如l=(1,2,3,4)
,def(x):返回x%2
和[在groupby中k,v的列表(v)(排序的(l),key=f)]
->[[1],[2],[3],[4]
错误;[list(v)对于k,v在groupby中(排序的(l,key=f),key=f)]
import collections
def regroup_by_dd(items, key=None):
result = collections.defaultdict(list)
callable_key = callable(key)
for item in items:
result[key(item) if callable_key else item].append(item)
return dict(result) # to be in line with other solutions
def regroup_by_sd(items, key=None):
result = {}
callable_key = callable(key)
for item in items:
key_value = key(item) if callable_key else item
result.setdefault(key_value, []).append(item)
return result
import itertools
def regroup_by_it(items, key=None):
seq = sorted(items, key=key)
result = {
key_value: list(group)
for key_value, group in itertools.groupby(seq, key)}
return result
def group_by(
seq,
key=None):
items = iter(seq)
try:
item = next(items)
except StopIteration:
return
else:
callable_key = callable(key)
last = key(item) if callable_key else item
i = j = 0
for i, item in enumerate(items, 1):
current = key(item) if callable_key else item
if last != current:
yield last, seq[j:i]
last = current
j = i
if i >= j:
yield last, seq[j:i + 1]
def regroup_by_gb(items, key=None):
return dict(group_by(sorted(items, key=key), key))
from operator import itemgetter
mylist = [['AB001', 22100],
['AB001', 32935],
['XC013', 99834],
['VD126', 18884],
['AB001', 4439],
['XC013', 86701]]
print(list(regroup_by_di(mylist, key=itemgetter(0)).values()))
# [[['AB001', 22100], ['AB001', 32935], ['AB001', 4439]], [['XC013', 99834], ['XC013', 86701]], [['VD126', 18884]]]