通过键将python列表分解为子列表的最有效方法,同时保留顺序

时间:2016-08-03 17:14:21

标签: python list

这里的第一次海报。如果我有一个包含具有不同信息的子列表的列表,并且我想将具有相同键值的所有子列表分组到一个新的子列表中(例如,基于键值的唯一列表),那么最有效的方法是什么这个?

示例:

A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]]

我希望将所有在' 0'中具有相同项目的子列表分组。索引到一个新的子列表,最好保留原始顺序:

B = [ [[1,2,3], [1,3,7], [1,2,4]], [[2,1,3],[2,3,8]], [[8,9,6]], [[3,7,9]] ] 

我已经多次解决了这个问题,但我想看看是否有更有效的方法来做到这一点。是的,出于这个原因我可以使用numpy包,但我对列表解决方案感兴趣。

通常情况下,我首先会在每个子列表的第一个索引中使用unique-ify项目(如果我不担心效率或顺序,则使用set方法),然后遍历整个列表,将子列表组合成一个新的子列表:

def getUniqueList(list):
    seen = []
    for e in list:
        if e not in seen:
        seen.append(e)
    return seen

def uniquify(list):
    # Get all items from the first column
    new_list = [item[0] for item in list]
    return getUniqueList(new_list)

def rearrangeList(A, A_0):
    B = []
    for i in range(len(A_0)):
        B.append([])
    for i in range(len(A)):
        index = A_0.index(A[i][0])
        B[index].append(A[i])
    return B

A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]]
A_0 = uniquify(A) # Contains all unique keys in index 0 of list A
B = rearrangeList(A, A_0)
print(B)

这个(我没有测试过,但这就是我编码的方式)导致:

  

B = [[[1,2,3],[1,3,7],[1,2,4]],[[2,1,3],[2,3,8]], [[8,9,6]],[[3,7,9]]]

我想知道1)在效率方面有更好的方法吗?2)有没有办法以较少的步骤(不一定有效,只是好奇)做到这一点。希望这个问题很好,但如果需要编辑,请告诉我!

3 个答案:

答案 0 :(得分:2)

基本上,您需要分组操作。使用字典按键分组,使用OrderedDict来保持顺序:

>>> from collections import OrderedDict
>>> groups = OrderedDict()
>>> A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]]
>>> key = lambda l: l[0]
>>> for sub in A:
...   groups.setdefault(key(sub),[]).append(sub)
... 
>>> groups
OrderedDict([(1, [[1, 2, 3], [1, 3, 7], [1, 2, 4]]), (2, [[2, 1, 3], [2, 3, 8]]), (8, [[8, 9, 6]]), (3, [[3, 7, 9]])])
>>> B = list(groups.values())
>>> B
[[[1, 2, 3], [1, 3, 7], [1, 2, 4]], [[2, 1, 3], [2, 3, 8]], [[8, 9, 6]], [[3, 7, 9]]]

答案 1 :(得分:1)

保留原始列表顺序的要求很有意思。

假设您的列表是A,并且您希望结果在B中,则以下代码在消耗输入时构造列表,因此保留了列表的原始顺序:

from collections import defaultdict
B=[]
reduce(lambda a,n: a[n[0]].append(n) or a,A,defaultdict(lambda: B.append([]) or B[-1]))

或以下更简单的代码在defaultdict中创建列表然后复制,但原始列表的顺序丢失:

from collections import defaultdict
B=reduce(lambda a,n: a[n[0]].append(n) or a,A,defaultdict(list)).values()

请注意,子列表将按其最初显示的顺序排列。

答案 2 :(得分:-1)

一所旧学校(但又好又简单)的方法:

A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]]
A = sorted(A, key=lambda x: x[0]) #sort just by the first index to preserve order
B = [[A[0]]]

for list in A[1:]:              # add to the last list or create new one
    if B[-1][-1][0]==list[0]:   #
        B[-1].append(list)      #
    else:                       #
        B.append([list])        #

B
#output: 
[[[1, 2, 3], [1, 3, 7], [1, 2, 4]], [[2, 1, 3], [2, 3, 8]], [[3, 7, 9]], [[8, 9, 6]]]