1

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.

divibisan
  • 11,659
  • 11
  • 40
  • 58
Integration
  • 195
  • 10
  • What is the objective here? It isn't clear how you get from your input to your output. "Combine" is an ambiguous term. – cs95 May 10 '18 at 05:45
  • @cᴏʟᴅsᴘᴇᴇᴅ I have expanded explanation. – Integration May 10 '18 at 05:48
  • Are the first elements unique across all tuples in a list? – cs95 May 10 '18 at 05:50
  • 1
    Additionally, are they always guaranteed to be in monotonically increasing order like this? – cs95 May 10 '18 at 05:50
  • @cᴏʟᴅsᴘᴇᴇᴅ There will never be a key-element repeat, and the pattern of unit change will always remain the same. – Integration May 10 '18 at 05:52
  • Ideally they would be in descending order of the highest element in each final tuple. However, its not a requirement. Thank you. – Integration May 10 '18 at 05:56
  • @chrisz I see what you mean. the horizontal order of the tuple does matter. I will add that to the question – Integration May 10 '18 at 05:57
  • If you have pandas, this is as simple as `pd.merge(*map(pd.DataFrame, [setA, setB]), on=0, how='left').astype(object).values.tolist()` – cs95 May 10 '18 at 05:59
  • @cᴏʟᴅsᴘᴇᴇᴅ it must be done with standard libraries and Python 2.6x, hence the difficulty Im having. – Integration May 10 '18 at 06:00

4 Answers4

5

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)]
cs95
  • 379,657
  • 97
  • 704
  • 746
  • @SynchronizeYourDogma Note that your input had an extra pair of braces which I removed. This answer assumes your question did not have that typo. – cs95 May 10 '18 at 06:03
  • @SynchronizeYourDogma If, your data actually has that absurd structure, then you'd need to do `setA = setA[0]; setB = setB[0]` and proceed in the same manner as before. – cs95 May 10 '18 at 06:07
2

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)
Mihai Alexandru-Ionut
  • 47,092
  • 13
  • 101
  • 128
1
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]]
Ken T
  • 2,255
  • 1
  • 23
  • 30
  • I'm not sure if those extra set of braces around the input are actually necessary or not. I've removed them under the assumption it was a mistake (seems pointless keeping it there to begin with)—and edited the question accordingly. – cs95 May 10 '18 at 06:05
  • @cᴏʟᴅsᴘᴇᴇᴅ OKAY, I gave the corresponding revised answer. BTW, what are the characters used in your name? They are special. – Ken T May 10 '18 at 06:18
  • 1
    [Relevant wikipedia article](https://en.wikipedia.org/wiki/Small_caps) ;-) – cs95 May 10 '18 at 06:19
0

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

`

Sushant
  • 511
  • 2
  • 13