2

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. i.e

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
1
  • 2
    Can you please add the expected output? Commented May 20, 2015 at 14:36

4 Answers 4

2

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
Sign up to request clarification or add additional context in comments.

6 Comments

Im testing this solution now, it looks promising. The only criteria for the resulting list is that it is parallel to the elements of the original (or new list).
You mean the list should be ordered according to the order of the tuples in t1? How do you want to handle the case that no tuple is present for a character?
Say t1 has 3 elements and t2 has 5. the resulting list returns a list [ 1,-1,0] respectively if all elements in t1 were found in t2. the default value if an element is not found in t2 would be 0. because in the end i take the list and combine it to t1 final_list = [ (f,r,u,chge) for (f,r,u), chge in zip(new,inc_dec_list)]
Okay. I added a new paragraph at the bottom that i think keeps the order you want.
awesome, going to test it. I also added my test case script that mimicks what I am trying to accomplish. Thank you
|
1

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)]

1 Comment

Hey chepner, nice answer again. However a small suggestion .. Do add a link to the docs as it will really help those who don't know about defaultdict and chain
0

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])

1 Comment

This solution will not find all the elements that do match, it will just dismiss if the current indexes dont match. However, if b[3] is equal to a[2] then I want to compare them. Thank you though, this was my initial try and noticed this.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.