简体   繁体   English

在元组列表中查找索引

[英]Find index inside a list of tuples

I have a list of tuples seg = [(874, 893), (964, 985), (1012, 1031)] and an index. 我有一个元组seg = [(874, 893), (964, 985), (1012, 1031)]和一个索引。 I want to check if the index is inside the range of those tuples, for example, 876 is while 870 is not. 我想检查索引是否在那些元组的范围内,例如876是,而870不是。

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 . 例如,对于index = 876返回1 ,对于index = 1015返回3

How can I do so? 我该怎么办?

You can use enumerate + next with generator expression: 您可以在生成器表达式中使用enumerate + next

>>> 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. 感谢@jpp提供有关next功能默认选项的提示 (It can be used in cases where the given index is not in any of the ranges represented by the tuples) (可以在给定索引不在元组表示的任何范围内的情况下使用)

As others have pointed out, you can use enumerate() to get the indexes. 正如其他人指出的那样,您可以使用enumerate()获取索引。 I'd also argue that if you are treating the tuples as ranges, you should make them ranges . 我还认为,如果将元组视为范围,则应将其设置为range This then makes the check to see if the value is inside the range very intuitive: value in range . 然后,这可以非常直观地检查值是否在范围内: 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). 显然,使用范围会产生一定的成本(如果您使用的是Python 2.x,这会比较大,因为它将生成所有值的实际列表,并且不幸的是, xrange()返回没有实现__contains__()对象)。 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. 根据情况,您也许可以只用范围结构替换元组结构,而不用做星形图。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM