Reputation: 893
I have a list of tuples seg = [(874, 893), (964, 985), (1012, 1031)]
and an index. I want to check if the index is inside the range of those tuples, for example, 876
is while 870
is not.
My code to do so is the following:
if [x for (x, y) in seg if x <= index <= y]:
print ("index inside the segment")
However, I also want to return if the index is in the first second ... segment of the list seg.
For example, for the index = 876
to return 1
and for the index = 1015
to return 3
.
How can I do so?
Upvotes: 1
Views: 2085
Reputation: 20424
You can use enumerate
+ next
with generator expression:
>>> seg = [(874, 893), (964, 985), (1012, 1031)]
>>> index = 876
>>> next((i for i, (s,f) in enumerate(seg) if s <= index <= f), None)
0
Or, if you want to iterate over:
>>> for i in (i for i, (s,f) in enumerate(seg) if s <= index <= f):
... print("in segment:", i)
...
in segment: 0
thanks @jpp
for the hint about the default option of the next
function. (It can be used in cases where the given index is not in any of the ranges represented by the tuples)
Upvotes: 8
Reputation: 89017
As others have pointed out, you can use enumerate()
to get the indexes. I'd also argue that if you are treating the tuples as ranges, you should make them ranges. This then makes the check to see if the value is inside the range very intuitive: value in range
.
import itertools
seg = [(874, 893), (964, 985), (1012, 1031)]
ranges = list(itertools.starmap(range, seg))
def test(value):
for i, valueRange in enumerate(ranges):
if value in valueRange:
return i # + 1 if you want to index from 1 as indicated.
# You could add some special case handling here if there is no match, like:
# throw NoSuchRangeException("The given value was not inside any of the ranges.")
print(test(876)) # 0
print(test(1015)) # 1
Obviously using ranges has some cost (if you are in Python 2.x, this is comparatively huge because it will make actual lists of all the values, and unfortunately xrange()
return objects without __contains__()
implemented). If you are doing this kind of thing in lots of places, it's much nicer, however.
You may be able to just replace your tuple construction with range construction, depending on the situation, rather than doing the starmap.
Upvotes: 3
Reputation: 2358
Assuming the following:
List is ordered
First number is less than second number
no overlapping
index=870
seg = [(874, 893), (964, 985), (1012, 1031)]
for i, t in enumerate(seg):
if index >= t[0] and index <= t[1]:
print i
Upvotes: 1