удалить наибольший из пересекающиеся элементов в списке кортежей
для решения задачи мне необходимо решить подзадачу:
Вариант А:
Дан список кортежей: both = [(1, 2), (4, 5), (6, 7), (7, 8)]
необходимо оставить меньший из кортежей, содержащих одинаковую цифру
т.е. в случае с примером необходимо получить: [(1, 2), (4, 5), (6, 7)]
Пробовал:
ans = []
for i in range(len(both)-1):
if set(both[i]) & set(both[i+1]):
ans.append(max(both[i], both[i+1]))
ans1 = []
for i in both:
if i not in ans:
ans1.append(i)
print(ans1)
т.е. сначало получил больший из двух пересекающихся кортежей, потом не взял его в новый список... но что то мне подсказывает что это некрасивое решение, вот и хотел бы спросить, как решить более изящно и по питоновски...
Вариант Б:
дано два списка кортежей:
a = [(4, 5), (7, 8)] и b = [(1, 2), (6, 7)]
необходимо собрать их в один список, в котором из двух содержащих одинаковые значения кортежей место займет меньший...
Ответы (2 шт):
Вариант №1:
both = [(1, 2), (4, 5), (6, 7), (7, 8)]
d = dict(both)
for k in dict(d):
if k in d.values():
d.pop(k)
continue
result = list(d.items())
print(result)
Вариант №2:
both = [(1, 2), (4, 5), (6, 7), (7, 8)]
result = []
for el in both:
if el[0] not in (n[1] for n in result):
result.append(el)
print(result)
Вариант №3:
both = [(1, 2), (4, 5), (6, 7), (7, 8)]
d = dict()
for el in both:
if el[0] not in d.values():
d[el[0]] = el[1]
result = list(d.items())
print(result)
Тесты производительности:
import time
def elapsed(f):
start = time.perf_counter()
r = f()
finish = time.perf_counter()
return (finish-start, r)
def f1(both):
d = dict(both)
for k in dict(d):
if k in d.values():
d.pop(k)
continue
return list(d.items())
def f2(both):
result = []
for el in both:
if el[0] not in (n[1] for n in result):
result.append(el)
return result
def f3(both):
d = dict()
for el in both:
if el[0] not in d.values():
d[el[0]] = el[1]
return list(d.items())
def test(both):
t1, r1 = elapsed(lambda: f1(both))
t2, r2 = elapsed(lambda: f2(both))
t3, r3 = elapsed(lambda: f3(both))
assert r1==r2
assert r2==r3
return t1, t2, t3
def main():
s1 = s2 = s3 = 0
both = []
for i in range(10**3):
t = test(both)
s1 += t[0]
s2 += t[1]
s3 += t[2]
both.append((i, i+1))
if not i%1000:
print(f'{s1:5.2f}', f'{s2:5.2f}', f'{s3:5.2f}')
main()
Вывод:
0.00 0.00 0.00
2.25 5.00 1.14
17.73 39.98 8.82
Как видно из тестов лучше всего использовать вариант №3.
можно еще такой вариант потестировать:
a,b = zip(*both)
ans = [both[i] for i in range(len(a)) if a[i] not in b]