简体   繁体   中英

comparing list of tuple elements python

I have a two list of tuples

t1 = [ ('a',3,4), ('b',3,4), ('c',4,5) ]
t2 = [ ('a',4,6), ('c',3,4), ('b',3,6), ('d',4,5) ]

Such that

  1. the order of the tuples may not be the same order and
  2. the lists may not contain the same amount of tuple elements.

My goal is to compare the two lists such that if the string element matches, then compare the last integer element in the tuple and return a list containing -1 if t1[2] < t2[2], 0 if they are equal and 1 if they are greater than.

I've tried different variations but the problem i have is finding a way to match the strings to do proper comparison.

return [diff_unique(x[2],y[2]) for x,y in zip(new_list,old_list) ]

Where diff_unique does the aforementioned comparison of the integers, and new_list is t1 and old_list is t2.

I've also tried this:

return [diff_unique(x[2],y[2]) for x,y in zip(new_list,old_list) if(x[0]==y[0]]

What I intend to do is use the returned list and create a new four-tuple list with the original t1 values along with the difference from the matching t2 tuple. ie

inc_dec_list = compare_list(new,old)
final_list = [ (f,r,u,chge) for (f,r,u), chge in zip(new,inc_dec_list)]

Where new = t1 and old = t2. This may have been an important detail, sorry I missed it.

Any help in the right direction?

Edit: I have added my test case program that mimicks what my original intent is for those who want to help. Thank you all.

import os 
import sys

old = [('a',10,1),('b',10,2),('c',100,4),('d',200,4),('f',45,2)]
new = [('a',10,2),('c',10,2),('b',100,2),('d',200,6),('e',233,4),('g',45,66)]


def diff_unique(a,b):
    print "a:{} = b:{}".format(a,b)
    if a < b:
        return -1
    elif a==b:
        return 0
    else:
        return 1

def compare_list(new_list, old_list):
    a = { t[0]:t[1:] for t in new_list } 
    b = { t[0]:t[1:] for t in old_list }
    common = list( set(a.keys())&set(b.keys()))
    return [diff_unique(a[key][1], b[key][1]) for key in common]
    #get common tuples
    #common = [x for x,y in zip(new_list,old_list) if x[0] == y[0] ]
    #compare common to old list
    #return [diff_unique(x[2],y[2]) for x,y in zip(new_list,old_list) ]

inc_dec_list = compare_list(new,old)
print inc_dec_list

final_list = [ (f,r,u,chge) for (f,r,u), chge in zip(new,inc_dec_list)]
print final_list

To match the tuples by string from different lists, you can use dict comprehension (order inside the tuples is preserved):

a = {t[0]:t[1:] for t in t1} # {'a': (3, 4), 'c': (4, 5), 'b': (3, 4)}
b = {t[0]:t[1:] for t in t1} # {'a': (4, 6), 'c': (3, 4), 'b': (3, 6), 'd': (4, 5)}

Then you can iterate over the keys of both dictionaries and do the comparison. Assuming you only want to do the comparison for keys/tuples present in t1 and t2 , you can join the keys using sets:

common_keys = list(set(a.keys())&set(b.keys()))

And finally compare the dictionary's items and create the list you want like this:

return [diff_unique(a[key][1],b[key][1]) for key in common_keys ]

If you need the output in the order of the alphabetically sorted characters, use the sorted function on the keys:

return [diff_unique(a[key][1],b[key][1]) for key in sorted(common_keys) ]

If you want all keys to be considered, you can do the following:

all_keys = list(set(a.keys()+b.keys()))
l = list()
for key in sorted(all_keys):
    try:
        l.append(diff_unique(a[key][1],b[key][1]))
    except KeyError:
        l.append("whatever you want")
return l

With the new information about what values should be returned in what order, the solution would be this:

ordered_keys = [t[0] for t in t1]
a = {t[0]:t[1:] for t in t1} # {'a': (3, 4), 'c': (4, 5), 'b': (3, 4)}
b = {t[0]:t[1:] for t in t1} # {'a': (4, 6), 'c': (3, 4), 'b': (3, 6), 'd': (4, 5)}
l = list()
for key in sorted(ordered_keys):
    try:
        l.append(diff_unique(a[key][1],b[key][1]))
    except KeyError:
        l.append(0) # default value
return l

First, build a default dictionary from each list, with the default value for a nonexistent key being a tuple whose last element is the smallest possible value for a comparison.

SMALL = (-float['inf'],)

from collections import defaultdict
d1 = defaultdict(lambda: SMALL, [(t[0], t[1:]) for t in t1])
d2 = defaultdict(lambda: SMALL, [(t[0], t[1:]) for t in t2])

Next, iterate over the keys in each dictionary (which can be created easily with itertools.chain ). You probably want to sort the keys for the resulting list to have any meaning (otherwise, how do you know which keys produced which of -1/0/1?)

from itertools import chain
all_keys = set(chain(d1, d2))
result = [cmp(d1[k][-1], d2[k][-1]) for k in sorted(all_keys)]

Here is a simple solution of your problem, It is not one line as you tried. I hope it will still help you

for a in t1:
    for b in t2:
        if a[0] != b[0]:
            continue
        return cmp(a[-1], b[-1])

In python 3.x , you can compare two lists of tuples a and b thus:

import operator

a = [(1,2),(3,4)]
b = [(3,4),(1,2)]
# convert both lists to sets before calling the eq function
print(operator.eq(set(a),set(b))) #True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM