Search code examples
pythonpython-2.xtransposeequalitytrailing

Remove trailing items of two lists if values at the same index are equal


I want to accomplish the following:

I have two lists a and b which are guaranteed to be of size 5. I now want to remove values from the end of both lists that are equal at the same indices / when zipped/transposed. As an example of input and expected output:

In:   a=[2,3,2,2,1], b=[2,3,4,1,1]
Out:  a=[2,3,2,2],   b=[2,3,4,1]

In:   a=[9,10,10,10,10], b=[10,10,10,10,10]
Out:  a=[9],             b=[10]

In:   a=[1,2,3,4,5], b=[1,2,3,4,5]
Out:  a=[],          b=[] 
# (a=[1], b=[1] or a=[1,2,3,4,5], b[1,2,3,4,5] are fine as well
#  for this last example, as long as there isn't any error)

In:  a=[10,10,10,10,10], b=[10,10,10,10,9]
Out: a=[10,10,10,10,10], b=[10,10,10,10,9]

I know how to remove all values that are equal at the same indices:

f = lambda a,b: [] if a==b else map(list, zip(*[(i,j) for(i,j) in zip(a,b) if i!=j]))[0]

Which I can then call as:

a,b = [2,3,2,2,1], [2,3,4,1,1]
A,B = f(a,b), f(b,a)

But this would result in A=[2,2], B=[4,1], also removing the leading values.

What would be the easiest approach to remove trailing values from both lists until a mismatch is found at the same index?
PS: This is for a code-golf challenge. I almost never program in Python, but if I would use it elsewhere I'd probably create variables for the zips instead of this quite unreadable single line I have above. Still, for this answer I would prefer as short as possible answers over readability, although it's not a requirement for this question. Just want to know how to accomplish it in general.


Solution

  • One approach is to use a generator expression to iterate over both lists starting from the end, and keep the first index where a match is found:

    a=[2,3,2,2,1]
    b=[2,3,4,1,1]
    
    ix = next((ix for ix,(i,j) in enumerate(zip(a[::-1],b[::-1])) if i != j), None) 
    

    Which you can then use to slice the lists (use an if statement to check if the returned values is None, which would mean that both lists are equal):

    if ix:
        print(a[:len(a)-ix])
        print(b[:len(b)-ix])
    # [2, 3, 2, 2]
    # [2, 3, 4, 1]
    

    And for your other example:

    a=[9,10,10,10,10]
    b=[10,10,10,10,10]
    
    ix = next(ix for ix,(i,j) in enumerate(zip(a[::-1],b[::-1])) if i != j)
    
    if ix:
        print(a[:len(a)-ix])
        print(b[:len(b)-ix])
    # [9]
    # [10]