快速删除连续重复的python

时间:2017-01-06 18:00:33

标签: python duplicates

我的问题类似于previous SO question 我有两个大的数据列表(近1.2亿个数据点),包含许多连续的重复项。我想删除连续的副本,如下所示

{{1}}

输出应为[1,2,3,4,5,1,2] 不幸的是,这非常慢,因为删除列表中的元素本身就是一个缓慢的操作。有什么方法可以加快这个过程吗?请注意,如上面的代码所示,我也需要跟踪索引i,以便我可以删除list2中的相应元素。

2 个答案:

答案 0 :(得分:6)

Python为您提供了这个groupby

>>> list1 = [1,1,1,1,1,1,2,3,4,4,5,1,2]
>>> from itertools import groupby
>>> [k for k,_ in groupby(list1)]
[1, 2, 3, 4, 5, 1, 2]

您可以使用keyfunc参数进行调整,以便同时处理第二个列表。

>>> list1 = [1,1,1,1,1,1,2,3,4,4,5,1,2]
>>> list2 = [9,9,9,8,8,8,7,7,7,6,6,6,5]
>>> from operator import itemgetter
>>> keyfunc = itemgetter(0)
>>> [next(g) for k,g in groupby(zip(list1, list2), keyfunc)]
[(1, 9), (2, 7), (3, 7), (4, 7), (5, 6), (1, 6), (2, 5)]

如果您想将这些对再次拆分为单独的序列:

>>> zip(*_)  # "unzip" them
[(1, 2, 3, 4, 5, 1, 2), (9, 7, 7, 7, 6, 6, 5)]

答案 1 :(得分:0)

您可以使用collections.deque及其最大len参数将窗口大小设置为2。然后只需比较窗口中2个条目的重复性,然后将结果附加到结果上即可。

def remove_adj_dups(x):
"""
:parameter x is something like '1, 1, 2, 3, 3'
    from an iterable such as a string or list or a generator
:return 1,2,3, as list
"""

    result = []
    from collections import deque
    d = deque([object()], maxlen=2)  # 1st entry is object() which only matches with itself. Kudos to Trey Hunner -->object()

    for i in x:
        d.append(i)
        a, b = d
        if a != b:
            result.append(b)
    return result

我生成了一个random list with duplicates,其中包含0到10之间的2000万个数字。

def random_nums_with_dups(number_range=None, range_len=None):
    """
    :parameter
    :param number_range: use the numbers between 0 and number_range. The smaller this is then the more dups
    :param range_len: max len of the results list used in the generator
    :return: a generator

    Note: If number_range = 2, then random binary is returned
    """

    import random
    return (random.choice(range(number_range)) for i in range(range_len))

然后我用

进行了测试
range_len = 2000000
def mytest():
    for i in [1]:
        return [remove_adj_dups(random_nums_with_dups(number_range=10, range_len=range_len))]
big_result = mytest()

big_result = mytest()[0]
print(len(big_result))

len在不到5秒的时间内为1800197(删除了读取的重复数据),其中包括随机列表生成器旋转。 我缺乏经验/不知道该如何提高内存使用效率。有人可以发表评论