IT业界:Python列表去重复项的N种方法

    作者:课课家教育更新于: 2020-06-16 14:20:01

    说明

    Python是一种解释型脚本语言,可以应用于以下领域:

    • Web 和 Internet开发
    • 科学计算和统计
    • 教育
    • 桌面界面开发
    • 软件开发
    • 后端开发

    随着人工智能的发展,Python变得越来越流行了。而Python语言中列表(List)与其他语言的数组(Array)类似,是一种有序的集合数据结构,但Python List可支持各种数据类型,长度也可动态调整,与JS中的数组或Java ArrayList很接近。在实际编程中,我们会遇到数组或列表去掉重复项的需求。那么在Python编程中,我们会有很多种方法来实现这个目标,有的新建列表来存储非重复项,有的则在原有基础上删除掉重复的项,有的则利用数据结构来达到去重复的目的。具体哪一种方法更好呢?只能说根据不同场景来选择一种,以下的N种方式将有助于对于基础算法和语言学习的理解。

     

    方式

    ## 1. 新建列表,如果新列表中不存在,则添加到新列表

     

    def unique(data):

     

        newList = []

     

        for item in data:

     

            if item not in newList:

     

                newList.append(item)

     

        print("for list + not in. data:", newList)

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    unique(data)

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")

     

     

    # result

     

    $ python -V

     

    Python 2.7.16

     

    $ python unique.py

     

    ('for list + not in. data:', ['a', 1, 2, 'b'])

     

    time:0.0441074371338 ms
    ## 2. 新建列表。根据下标判断是否存在新列表中,如果新列表中不存在则添加到新列表

     

    def unique(data):

     

        newList = []

     

        for i in range(len(data)):

     

            if data[i] not in newList:

     

                newList.append(data[i])

     

        return newList

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("for range + not in. data:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 3. 通过index找不到该项,则追加到新列表中。index找不到会报错,因此放在异常处理里

     

    def unique(data):

     

        newList = []

     

        for i in range(len(data)):

     

            item = data[i]

     

            try:

     

                if (newList.index(item) < 0):

     

                    print('newList:', newList)

     

            except ValueError:

     

                newList.append(item)

     

        return newList

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("list index + except:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 4. 新建列表,两个循环。如果内循环与外循环项相同,且下标相同就添加到新列表,其余忽略

     

    def unique(data):

     

        newList = []

     

        for i in range(len(data)):

     

            j = 0

     

            while j < i:

     

                j += 1

     

                if data[i] == data[j]:

     

                    if (i == j):

     

                        newList.append(data[i])

     

                    break

     

        return newList

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("new list + for. newList:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 5. 在原有列表上移除重复项目。自后往前遍历,逐个与前面项比较,如果值相同且下标相同,则移除当前项。

     

    def unique(data):

     

        l = len(data)

     

        while (l > 0):

     

            l -= 1

     

            i = l

     

            while i > 0:

     

                i -= 1

     

                if data[i] == data[l]:

     

                    del data[l]

     

                    break

     

        return data

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("one list while. last -> first result. data:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 6. 在原有列表上移除重复项目。自前往后遍历,逐个与后面项比较,如果值相同且下标相同,则移除当前项。

     

    def unique(data):

     

        l = len(data)

     

        i = 0

     

        while i < l:

     

            j = i + 1

     

            while j < l:

     

                if data[i] == data[j]:

     

                    del data[j]

     

                    l -= 1

     

                    i -= 1

     

                    break

     

                j += 1

     

            i += 1

     

        return data

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("one list while. first -> last result. data:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 7. 新建列表。遍历列表,利用index比较出现的位置,如果出现在第一次的位置则追加到新数组

     

    def unique(data):

     

        newList = []

     

        for i in range(len(data)):

     

            if i == data.index(data[i]):

     

                newList.append(data[i])

     

        return newList

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("for range + index. data:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 8. 利用字典属性唯一性来实现去重复。

     

    def unique(data):

     

        obj = {}

     

        for item in data:

     

            obj[item] = item

     

        return obj.values()

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("list + dict:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 9. 利用filter函数,即把不符合条件的过滤掉。这里filter不支持下标,因此需要借助外部列表存储不重复项

     

    def uniq(item):

     

        i = data.index(item)

     

        if (item not in newList):

     

            newList.append(item)

     

            return True

     

        return False

     

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    newList = []

     

    print('filter + list + not in: ', filter(uniq, data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 10. 利用字典结合过滤来实现去重复。

     

    def unique(item):

     

        if obj.get(item) == None:

     

            obj[item] = item

     

            return True

     

        return False

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    obj = {}

     

    print("filter + dict + get:", filter(unique, data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 11. 利用map来实现去重复。与map与filter类似,是一个高阶函数。可以针对其中项逐个修改操作。

     

    ## 与filter不同map会保留原有项目,并不会删除,因此值可以改为None,然后再过滤掉。

     

    def unique(item):

     

        if item not in newList:

     

            newList.append(item)

     

            return item

     

        return None

     

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    newList = []

     

    start_time = time.time()

     

     

    print("list from Map:", filter(lambda item: item != None, map(unique, data)))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 12. 利用set数据结构里key的唯一性来去重复

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    print("from Set:", set(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 13. 提前排序,从后向前遍历,将当前项与前一项对比,如果重复则移除当前项

     

    def unique(data):

     

        data.sort()

     

        l = len(data)

     

        while (l > 0):

     

            l -= 1

     

            if (data[l] == data[l - 1]):

     

                data.remove(data[l])

     

        return data

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("sort + remove:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 14. 提前排序,自前往后遍历,将当前项与后一项对比,如果重复则移除当前项

     

    def unique(data):

     

        """

     

         in python 3: TypeError: '<' not supported between instances of 'int' and 'str'

     

         need to keep the same Type of member in List

     

        """

     

        data.sort()

     

        l = len(data) - 1

     

        i = 0

     

        while i < l:

     

            if (data[i] == data[i + 1]):

     

                del data[i]

     

                i -= 1

     

                l -= 1

     

            i += 1

     

        return data

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("sort+del ASE:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 15. 利用reduce函数来去重复。reduce具有累计的作用,判断如果不在累计结果中出现,则追加到结果中。

     

    import functools

     

    def unique(data):

     

        newList = []

     

     

        def foo(result, item):

     

            if isinstance(result, list) == False:

     

                result = [result]

     

            return result if item in result else result + [item]

     

     

        return functools.reduce(foo, data)

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("functools.reduce:", unique(data))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 16. 利用递归调用来去重复。递归自后往前逐个调用,当长度为1时终止。

     

    ## 当后一项与前任一项相同说明有重复,则删除当前项。相当于利用自我调用来替换循环

     

    def recursionUnique(data, len):

     

        if (len <= 1):

     

            return data

     

     

        l = len

     

        last = l - 1

     

        isRepeat = False

     

     

        while (l > 1):

     

            l -= 1

     

            if (data[last] == data[l - 1]):

     

                isRepeat = True

     

                break

     

     

        if (isRepeat):

     

            del data[last]

     

     

        return recursionUnique(data, len - 1)

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("recursionUnique:", recursionUnique(data, len(data)))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")
    ## 17. 利用递归调用来去重复的另外一种方式。递归自后往前逐个调用,当长度为1时终止。

     

    ## 与上一个递归不同,这里将不重复的项目作为结果拼接起来

     

    def recursionUniqueNew(data, len):

     

        if (len <= 1):

     

            return data

     

     

        l = len

     

        last = l - 1

     

        isRepeat = False

     

        while (l > 1):

     

            l -= 1

     

            if (data[last] == data[l - 1]):

     

                isRepeat = True

     

                break

     

     

        if (isRepeat):

     

            del data[last:]

     

            result = []

     

        else:

     

            result = [data[last]]

     

     

        return recursionUniqueNew(data, len - 1) + result

     

     

    # test

     

    data = ['a', 'a', 1, 1, 2, 2, 'b', 'b', 2, 1]

     

    start_time = time.time()

     

    print("recursionUniqueNew:", recursionUniqueNew(data, len(data)))

     

    print("time:" + str((time.time() - start_time) * 1000) + " ms")

     

    讨论

    从以上例子上可以看出,相对来讲,Python比起其它语言要灵活得多,与JS并列最流行的脚本类语言,这也就是为何Python如此流行的原因吧。

    哪一种方式更适合呢?你常用那种方式来实现去重复项?新建数组、非新建、借助DIct或Set等结构,亦或是其它方式?

    Python是一种计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。

课课家教育

未登录