'Using bisect in a list of tuples?
I'm trying to figure out how to use bisect in a list of tuples for example
[(3, 1), (2, 2), (5, 6)]
How can I bisect this list according to the [1] in each tuple?
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,)
And I'm inserting to bisect
idx = bisect.bisect(fst, tup1[1]+tup2[1])
Which gives me unorderable types: int() < tuple()
Solution 1:[1]
In some cases just the simple
bisect(list_of_tuples, (3, None))
will be enough.
Because None will compare less than any integer, this will give you the index of the first tuple starting with at least 3, or len(list_of_tuples) if all of them are smaller than 3. Note that list_of_tuples is sorted.
Solution 2:[2]
Check the bottom section of the documentation: http://docs.python.org/3/library/bisect.html. If you want to compare to something else than the element itself, you should create a separate list of so-called keys. In your case a list of ints containing only [1] of the tuple. Use that second list to compute the index with bisect. Then use that to both insert the element into the original (list of tuples) and the key ([1] of the tuple) into the new list of keys (list of ints).
Solution 3:[3]
Answers that suggest transforming the input list are defeating the purpose of bisect by converting what should be an O(log n) into an O(n) operation. A better solution is to use a view on the input:
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)
Solution 4:[4]
Since version 3.10 you can pass a key to bisect methods to specify the index you want to search on - more info here:
key specifies a key function of one argument that is used to extract a comparison key from each element in the array. To support searching complex records, the key function is not applied to the x value.
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])
Solution 5:[5]
I faced the same issue. I was storing list of (file_id, word_frequency) tuples and wanted to get the list sorted by second element in the tuple which is word_frequency. I did some research and found out how python compares tuples which is describe here https://howtodoinjava.com/python/compare-tuples/.
Essentially it looks at first element of two tuples and takes the smaller one. If the first elements are same then it compares second values an so on.
So what I did was exchanged the elements in tuple (word_frequency, file_id). Now I got my list sorted according to word frequency using bisect.
Hope this helps
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Evgeni Sergeev |
| Solution 2 | |
| Solution 3 | Brent |
| Solution 4 | Yar |
| Solution 5 | samsri |
