Используя bisect в списке кортежей?
Я пытаюсь выяснить, как использовать bisect в списке кортежей, например
[(3, 1), (2, 2), (5, 6)]
Как я могу разделить этот список в соответствии с [1] в каждом кортеже?
list_dict [(69, 8), (70, 8), ((65, 67), 6)]
tup1,tup2 (69, 8) (70, 8)
list_dict [((65, 67), 6)]
fst, snd ((65, 67),) (6,)
И я вставляю, чтобы разделить
idx = bisect.bisect(fst, tup1[1]+tup2[1])
Что дает мне unorderable types: int() < tuple()
6 ответов
Вы можете разделить значения в отдельные списки.
from bisect import bisect
data = [(3, 1), (2, 2), (5, 6)]
fst, snd = zip(*data)
idx = bisect(fst, 2)
Обратите внимание, что для bisect
на работу, ваши данные действительно должны быть упорядочены...
В некоторых случаях просто
bisect(list_of_tuples, (3, None))
будет достаточно.
Так как None
будет сравнивать меньше любого целого числа, это даст вам индекс первого кортежа, начинающийся как минимум с 3, или len(list_of_tuples)
если все они меньше 3. Обратите внимание, что list_of_tuples
отсортировано
Начиная с версии
3.10
вы можете передать ключ
bisect
методы для указания индекса, по которому вы хотите выполнить поиск — больше информации здесь:
key указывает ключевую функцию одного аргумента, которая используется для извлечения ключа сравнения из каждого элемента в массиве. Для поддержки поиска сложных записей функция key не применяется к значению x.
import bisect
tuple_list = [(4, 117), (10, 129), (30, 197)]
# search among first indices - returns 1
bisect.bisect_left(tuple_list, 10, key=lambda i: i[0])
# search among second indices - returns 1
bisect.bisect_left(tuple_list, 129, key=lambda i: i[1])
# 2
bisect.bisect_left(tuple_list, 130, key=lambda i: i[1])
Проверьте нижний раздел документации: http://docs.python.org/3/library/bisect.html. Если вы хотите сравнить с чем-то другим, кроме самого элемента, вы должны создать отдельный список так называемых ключей. В вашем случае список целых, содержащий только [1] кортежа. Используйте этот второй список, чтобы вычислить индекс с помощью bisect. Затем используйте это, чтобы вставить элемент в оригинал (список кортежей) и ключ ([1] кортежа) в новый список ключей (список целых).
Ответы, предлагающие преобразовать входной список, противоречат цели деления пополам, преобразовывая то, что должно быть O(log n), в операцию O(n). Лучшее решение - использовать представление на входе:
class _list_view:
def __init__(self, a, key):
self.a = a
self.key = key
def __getitem__(self, index):
return self.key(self.a[index])
def bisect_left(a, x, lo=0, hi=None, key=id):
from bisect import bisect_left
hi = hi or len(a)
if key == id:
return bisect_left(a, x, lo, hi)
return bisect_left(_list_view(a, key), x, lo, hi)
Я столкнулся с той же проблемой. Я хранил список(file_id, word_frequency)
кортежей и хотел получить список, отсортированный по второму элементу в кортеже, который word_frequency
. Я провел небольшое исследование и выяснил, как python сравнивает кортежи, описанные здесь https://howtodoinjava.com/python/compare-tuples/.
По сути, он смотрит на первый элемент двух кортежей и берет меньший. Если первые элементы совпадают, сравниваются вторые значения и так далее.
Итак, я заменил элементы в кортеже (word_frequency, file_id)
. Теперь мой список отсортирован по частоте слов с помощью биссектрисы.
Надеюсь это поможет