Joining two sets of tuples at a common value

702 views Asked by At

Given:

setA = [(1, 25), (2, 24), (3, 23), (4, 22), (5, 21), (6, 20), 
         (7, 19), (8, 18), (9, 17), (10, 16), (11, 15), (12, 14), 
         (13, 13),(14, 12), (15, 11), (16, 10), (17, 9), (18, 8), 
         (19, 7),(20, 6), (21, 5), (22, 4), (23, 3), (24, 2), (25, 1)]

setB = [(1, 19), (2, 18), (3, 17), (4, 16), (5, 15), (6, 14), (7, 13),
         (8, 12), (9, 11), (10, 10), (11, 9), (12, 8), (13, 7), (14, 6),
         (15, 5), (16, 4), (17, 3), (18, 2), (19, 1)]

How can I combine the two sets using the first element of each tuple in each set as a common key value. So for tuple at position 1 in each set it would be (1,25) and (1,19) respectively. Joined together would yield: (25,1,19)

(25,1,19)
(24,2,18)
(23,3,17)
...
(7,19,1)
(6,20,none)
...
(2,24,none)
(1,25,none)

Note: that order of output tuple must be maintained. Example:

(setA value, common value, setB value)
(setA value, common value, setB value)etc...

Note: Must use Python 2.7x standard libraries

I'm trying to do something like [(a,b,c) for (a,b),(b,c) in zip(setA,setB)] but I don't fully understand the proper syntax and logic.

Thank you.

4

There are 4 answers

3
Ken T On
setA = [(1, 25), (2, 24), (3, 23), (4, 22), (5, 21), (6, 20), 
         (7, 19), (8, 18), (9, 17), (10, 16), (11, 15), (12, 14), 
         (13, 13),(14, 12), (15, 11), (16, 10), (17, 9), (18, 8), 
         (19, 7),(20, 6), (21, 5), (22, 4), (23, 3), (24, 2), (25, 1)]

setB = [(1, 19), (2, 18), (3, 17), (4, 16), (5, 15), (6, 14), (7, 13),
         (8, 12), (9, 11), (10, 10), (11, 9), (12, 8), (13, 7), (14, 6),
         (15, 5), (16, 4), (17, 3), (18, 2), (19, 1)]
la, lb = len(setA), len(setB)
temp=[[setA[i][1] if i<la else None, i+1, setB[i][1] if i<lb else None] for i in range(0,max(la,lb))]

[[25, 1, 19],
 [24, 2, 18],
 [23, 3, 17],
 [22, 4, 16],
 [21, 5, 15],
 [20, 6, 14],
 [19, 7, 13],
 [18, 8, 12],
 [17, 9, 11],
 [16, 10, 10],
 [15, 11, 9],
 [14, 12, 8],
 [13, 13, 7],
 [12, 14, 6],
 [11, 15, 5],
 [10, 16, 4],
 [9, 17, 3],
 [8, 18, 2],
 [7, 19, 1],
 [6, 20, None],
 [5, 21, None],
 [4, 22, None],
 [3, 23, None],
 [2, 24, None],
 [1, 25, None]]
2
this be Shiva On

Seems like what you want can be implemented as easily as a dictionary lookup on setB inside a list comprehension.

mapping = dict(setB)
out = [(b, a, mapping.get(a)) for a, b in setA]

print(out)
[(25, 1, 19),
 (24, 2, 18),
 (23, 3, 17),
 (22, 4, 16),
 (21, 5, 15),
 (20, 6, 14),
 (19, 7, 13),
 (18, 8, 12),
 (17, 9, 11),
 (16, 10, 10),
 (15, 11, 9),
 (14, 12, 8),
 (13, 13, 7),
 (12, 14, 6),
 (11, 15, 5),
 (10, 16, 4),
 (9, 17, 3),
 (8, 18, 2),
 (7, 19, 1),
 (6, 20, None),
 (5, 21, None),
 (4, 22, None),
 (3, 23, None),
 (2, 24, None),
 (1, 25, None)]
0
Mihai Alexandru-Ionut On

Since our lists have different size zip is not a solution.

One solution could be using zip_longest method from itertools package.

finalSet = [(b, a, c[1] if c is not None else c) for (a,b), c in zip_longest(*setA,*setB)]

Output

(25, 1, 19)
(24, 2, 18)
(23, 3, 17)
(22, 4, 16)
(21, 5, 15)
(20, 6, 14)
(19, 7, 13)
(18, 8, 12)
(17, 9, 11)
(16, 10, 10)
(15, 11, 9)
(14, 12, 8)
(13, 13, 7)
(12, 14, 6)
(11, 15, 5)
(10, 16, 4)
(9, 17, 3)
(8, 18, 2)
(7, 19, 1)
(6, 20, None)
(5, 21, None)
(4, 22, None)
(3, 23, None)
(2, 24, None)
(1, 25, None)
0
Sushant On

If you want setC in the same format as setA and setB. I think this workaround will do. Entering values directly as tuple is not possible as tuples are immutable and hence we append the new tuples as list and then convert it to a tuple. `

setC = []
i=0
while setA[0][i][0]== setB[0][i][0] and (i < min(len(setA[0]), len(setB[0]))-1):
    setC.append((setA[0][i][1],setA[0][i][0], setB[0][i][1]))
    i+=1
setC = [tuple(setC)]

`