Subtracting two lists in Python

前端 未结 13 1523
一整个雨季
一整个雨季 2020-12-02 15:31

In Python, How can one subtract two non-unique, unordered lists? Say we have a = [0,1,2,1,0] and b = [0, 1, 1] I\'d like to do something like

相关标签:
13条回答
  • 2020-12-02 16:06

    I attempted to find a more elegant solution, but the best I could do was basically the same thing that Dyno Fu said:

    from copy import copy
    
    def subtract_lists(a, b):
        """
        >>> a = [0, 1, 2, 1, 0]
        >>> b = [0, 1, 1]
        >>> subtract_lists(a, b)
        [2, 0]
    
        >>> import random
        >>> size = 10000
        >>> a = [random.randrange(100) for _ in range(size)]
        >>> b = [random.randrange(100) for _ in range(size)]
        >>> c = subtract_lists(a, b)
        >>> assert all((x in a) for x in c)
        """
        a = copy(a)
        for x in b:
            if x in a:
                a.remove(x)
        return a
    
    0 讨论(0)
  • 2020-12-02 16:08

    I know "for" is not what you want, but it's simple and clear:

    for x in b:
      a.remove(x)
    

    Or if members of b might not be in a then use:

    for x in b:
      if x in a:
        a.remove(x)
    
    0 讨论(0)
  • 2020-12-02 16:08

    to use list comprehension:

    [i for i in a if not i in b or b.remove(i)]
    

    would do the trick. It would change b in the process though. But I agree with jkp and Dyno Fu that using a for loop would be better.

    Perhaps someone can create a better example that uses list comprehension but still is KISS?

    0 讨论(0)
  • 2020-12-02 16:08

    You can use the map construct to do this. It looks quite ok, but beware that the map line itself will return a list of Nones.

    a = [1, 2, 3]
    b = [2, 3]
    
    map(lambda x:a.remove(x), b)
    a
    
    0 讨论(0)
  • 2020-12-02 16:14

    Here's a relatively long but efficient and readable solution. It's O(n).

    def list_diff(list1, list2):
        counts = {}
        for x in list1:
            try:
                counts[x] += 1
            except:
                counts[x] = 1
        for x in list2:
            try:
                counts[x] -= 1
                if counts[x] < 0:
                    raise ValueError('All elements of list2 not in list2')
            except:
                raise ValueError('All elements of list2 not in list1') 
        result = []
        for k, v in counts.iteritems():
            result += v*[k] 
        return result
    
    a = [0, 1, 1, 2, 0]
    b = [0, 1, 1]
    %timeit list_diff(a, b)
    %timeit list_diff(1000*a, 1000*b)
    %timeit list_diff(1000000*a, 1000000*b)
    100000 loops, best of 3: 4.8 µs per loop
    1000 loops, best of 3: 1.18 ms per loop
    1 loops, best of 3: 1.21 s per loop
    
    0 讨论(0)
  • 2020-12-02 16:16
    c = [i for i in b if i not in a]
    
    0 讨论(0)
提交回复
热议问题