简体   繁体   中英

Get paired element from a list of tuples in Python

Suppose I have a list of tuples like this (without duplicates of any number):

lst = [(4, 1), (3, 8), (2, 9), (5, 6), (7, 0)]

I know an element value a and I want to find the paired value b .
However, I do not know if a is the first or the second element of the tuple.

Is there a way to find it easily and cleanly?

I tried this:

a = 8
pair = next(t for t in lst if t[0] == a or t[1] == a)
b = pair[0] if pair[1] == a else pair[1]

This does not look good... Does something smarter exist?

There exists a really cool trick for bi-directional maps in O(n). First you must flatten your list:

l = [1, 4, 3, 8, 9, 2, 5, 6, 7, 0]

Then finding the associated element of one is really simple:

a = 8
b = l[l.index(a) ^ 1]

This works because xor'ing a number with 1 adds one if the number is even, and subtracts one if it is odd.

Use list comprehension.

>>> lst = [(1, 4), (3, 8), (9, 2), (5, 6), (7, 0)]
>>> next(y if 8 == x else x for x,y in lst if 8 in (x,y))
3
>>> next(x[1] if 8 == x[0] else x[0] for x in lst if 8 in x)
3

What about:

>>> lst = [(1, 4), (3, 8), (9, 2), (5, 6), (7, 0)]

>>> a = 8
>>> next([i[i.index(a) ^ 1] for i in lst if a in i])
3

>>> a = 4
>>> next(i[i.index(a) ^ 1] for i in lst if a in i)
1

>>> a = 7
>>> next(i[i.index(a) ^ 1] for i in lst if a in i)
0

If your lst is not changed, and you're performing multiple lookups, you can build a lookup table in linear time ( O(n) ) to get answer in constant time ( O(1) ) or close to it in average case.

If your lst contains consecutive integers, and one of them is 0 , you can use list as lookup table to get O(1) lookup:

lookup = [None] * len(lst) * 2
for x, y in lst:
     lookup[x] = y
     lookup[y] = x

print(lookup[4]) # 1    

If not, you can use dict instead (slower lookup, more possibilities). You can easily switch to it at any time, because it can be built similar to the list above:

lookup = {}
for x, y in lst:
    lookup[x] = y
    lookup[y] = x

It can also be built in functional way:

from itertools import chain
flatten = chain.from_iterable
dct = dict(flatten(((x, y), (y, x)) for x, y in lst))

You can do it in this way

lst = [(4, 1), (3, 8), (2, 9), (5, 6), (7, 0)]

#number to be searched
num = 3

x = list(filter(lambda y: num in y, lst))

if x:
    x = list(x[0])
    x.remove(num)
    print(x)
else:
    print('Not Found')

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