Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare two lists of tuples

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])))
like image 699
Ron Avatar asked Apr 06 '17 13:04

Ron


People also ask

How do you compare two list tuples in Python?

Method #1 : Using == operator This is the simplest and elegant way to perform this task. It also checks for equality of tuple indices with one other.

How do you compare two tuples?

Rules for comparing tuples Compare the n-th items of both tuple (starting with the zero-th index) using the == operator. If both are equal, repeat this step with the next item. For two unequal items, the item that is “less than” makes the tuple, that contains it, also “less than” the other tuple.

How do you compare two lists in Python?

The set() function and == operator Python set() function manipulate the list into the set without taking care of the order of elements. Besides, we use the equal to operator (==) to compare the data items of the list.


3 Answers

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')}
like image 127
Brian Rodriguez Avatar answered Oct 18 '22 12:10

Brian Rodriguez


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))
like image 26
holdenweb Avatar answered Oct 18 '22 12:10

holdenweb


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)
like image 24
McGrady Avatar answered Oct 18 '22 13:10

McGrady