Compare two lists of tuples

15,370

Solution 1

A set is a great tool for finding such mismatches:

>>> old = [('ver','1121'),('sign','89'),('address','A45'),('type','00')]
>>> new = [('ver','1121'),('sign','89'),('type','01')]

>>> print('no longer there:', set(old) - set(new))
no longer there: {('type', '00'), ('address', 'A45')}

>>> print('newly added:', set(new) - set(old))
newly added: {('type', '01')}

>>> print('still there:', set(old) & set(new))
still there: {('sign', '89'), ('ver', '1121')}

Solution 2

What about this:

n,o=dict(new),dict(old)
for i in n:
    print "{0:10}:{2:8} {3:8} {1}".format(*(("Match","") if o.get(i)==n[i] else ("Mismatch",o.get(i,i)))+ (i,n[i]))

Output:

Mismatch  :type     01       00
Match     :ver      1121     
Match     :sign     89      

If you need the order, try to use OrderedDict:

from collections import OrderedDict
n,o=OrderedDict(new),OrderedDict(old)

Solution 3

Sometimes a list comprehension isn't the answer. This may be one of those times. Also, you don't handle the case where a key is present in old but not in new - I include that case here, though you can chop out that code if it isn't relevant. You could similarly handle the case of keys missing from new, but I didn't go that far.

old = [('ver','1121'),('sign','89'),('address','A45'),('type','00')]
new = [('ver','1121'),('sign','89'),('type','01'),("sneaky", 'not there before')]
formatter = "{:12}: {:8} = {}".format
newfmter = "{} (old : {})".format

for (kn, vn) in new:
    if any(ko==kn for (ko, vo) in old):
        ko, vo = [(ko, vo) for (ko, vo) in old if ko==kn][0]
        if vo==vn:
            print(formatter("Match", ko, vo))
        else:
            print(formatter("Mismatch", kn, newfmter(vn, vo)))
    else:
        print(formatter("New", kn, vn))
Share:
15,370
Ron
Author by

Ron

Updated on June 04, 2022

Comments

  • Ron
    Ron over 1 year
    old = [('ver','1121'),('sign','89'),('address','A45'),('type','00')]
    new = [('ver','1121'),('sign','89'),('type','01')]
    

    I need to compare the new list against old one based on first element of the tuples, and show the difference between whatever elements new list has, so that the output should look like:

    Match     : ver   =   1121
    Match     : sign  =   89
    Mismatch  : type  =   01 (old : 00)
    

    I could get all the matching tuples with below list comprehension but could not think beyond it.

    my_list = [(a,b) for (a,b) in new for (c,d) in old  if ((a==c) and (b==d))]
    print( my_list)
    

    Please suggest me a way to do it.

    EDIT

    I am sorry for not being clear on my question , I did not mention one more thing, the keys in the list can be repetitive, meaning the list can be like:

    old = [('ver','1121'),('sign','89'),('address','A45'),('type','00'),('ver','sorry')]
    
    new = [('ver','1121'),('sign','89'),('type','01'),('ver','sorry)]
    

    UPDATE

    Thanks to @holdenweb, I've made some changes to his code and this seems to be providing the expected output, please suggest if there are any flaws.

    old = [('ver','1121'),('sign','89'),('address','A45'),('type','00'),('ver','works?')]
    new = [('ver','1121'),('sign','89'),('type','01'),('ver','This')]
    
    formatter = "{:12}: {:8} = {}".format
    newfmter = "{} (old : {})".format
    
    kv_old = []
    for i,(kn, vn) in enumerate(new):
        vo = [(j,(ko,vo)) for j,(ko, vo) in enumerate(old) if (ko==kn) ]
        for idx,(key,val) in vo:
            if idx >=i:
                kv_old = [key,val]
                break;
    
        if kv_old[1]==vn:
            print(formatter("Match", kv_old[0], kv_old[1]))
        else:
            print(formatter("Mismatch", kn, newfmter(vn, kv_old[1])))