节省时间从Python的嵌套列表中删除反向重复吗?

时间:2019-03-26 21:02:57

标签: python list duplicates reverse detection

我有一个包含数百万其他列表的嵌套(使用元组atm)。对于每个列表,一个元素只能包含一次。我以为每个列表都是唯一的,所以我都需要它们,但是最近我意识到我的嵌套列表包含这样的对:

listA = ('77', '131', '212', '69')
listB = ('69', '212', '131', '77')

虽然listA和listB是唯一的,但是一个只是另一个的反向副本。我需要保留每种独特的组合,因为顺序很重要。

listC = ('131', '69', '77', '212')

因此listC在使用相同元素时,由于顺序而被认为是唯一的,因此需要保留。

如果我删除所有重复项,则可以将嵌套列表缩减很多(大约一半),但是我找不到一种省时的方法。

因为最好在将这些反向重复添加到我的嵌套列表之前就将它们消除,所以在下面,我包括了用于创建列表的类。

class Graph(object):

    def __init__(self, graph_dict=None):
        """ Initializes a graph object.
            If no dictionary or None is given,
            an empty dictionary will be used. """
        if graph_dict == None:
            graph_dict = {}
        self.__graph_dict = graph_dict

    def find_all_paths(self, start_vertex, end_vertex, path=[]):
        """ Find all paths from start_vertex to end_vertex in graph """
        graph = self.__graph_dict
        path = path + [start_vertex]        
        if start_vertex == end_vertex:
            return [path]
        if start_vertex not in graph:
            return []
        paths = []
        for vertex in graph[start_vertex]:
            if vertex not in path:
                extended_paths = self.find_all_paths(vertex, end_vertex, path)
                for p in extended_paths:
                    if len(p) >= 2:
                        p = tuple(p)
                        paths.append(p)
        return paths

graph = Graph(vertexGraphDict)
nestedList= graph.find_all_paths(begin, end)

vertexGraphDict只是一个作为键的顶点字典,其值是它所连接的其他顶点的列表。

我尝试使用以下方法消除反向重复:

reversedLists = []
for item in nestedLists:
    if item in reversedLists:
        nestedLists.remove(item)
    else:
        revItem = item[::-1] 
        reversedLists.append(revItem)

此方法非常慢。在删除类中的行p = tuple(p)之后,我还尝试了revItem = list(reversed(item));也很慢在列表制作过程中尝试这些方法可以节省总体时间,但并不能加快消除过程的速度,这很关键。

2 个答案:

答案 0 :(得分:3)

仅当最后一项低于第一项且值是元组本身时,才可以建立一个OrderedDict,其键是相反的元组,然后获取该值的列表。 OrderedDict

from collections import OrderedDict
l = [
    ('77', '131', '212', '69'),
    ('69', '212', '131', '77'),
    ('1', '2', '3', '4'),
    ('4', '1', '2', '3'),
    ('4', '3', '2', '1')
]
list(OrderedDict((t[::-1] if t[-1] < t[0] else t, t) for t in l).values())

或者,如果您使用的是Python 3.7或更高版本(按字典键排序),则可以使用字典代替OrderedDict

list({t[::-1] if t[-1] < t[0] else t: t for t in l}.values())

这将返回:

[('69', '212', '131', '77'), ('4', '3', '2', '1'), ('4', '1', '2', '3')]

答案 1 :(得分:0)

我的方法是将每个元组切换到一个列表,将其反转,再将其切换回一个元组,并从列表中删除(反转的)元组(如果它是其中的一部分)。

l = [
    ('77', '131', '212', '69'),
    ('69', '212', '131', '77'),
    ('1', '2', '3', '4'),
    ('4', '1', '2', '3'),
    ('4', '3', '2', '1')
]

for t in l:
    lr = list(t)
    lr.reverse()
    tr = tuple(lr)
    if tr in l:
        l.remove(tr)

print(l)

我不知道它的计算速度如何,但是输出就在这里。

[('77', '131', '212', '69'), ('1', '2', '3', '4'), ('4', '1', '2', '3')]