【问题标题】:Python find continuous interesctions of intervalsPython找到区间的连续交点
【发布时间】:2013-09-13 02:34:34
【问题描述】:

我厌倦了多种方法,但未能完成这项工作。他们都只使用 2 个列表或列表范围。 最有希望的是:

infile = open('file','r')

for line in infile:
    line = line.split()
    f = range(int(line[0]),int(line[1]))

results_union = set().union(*f)
print results_union

我有一个文件的开始,结束位置是这样的:(排序)

1 5
1 3
1 2
2 4
3 6
9 11
9 16
12 17

我希望输出是:

1 6
9 17

【问题讨论】:

  • 那么,您是在尝试对输入范围内的连续片段进行分组吗?
  • 是的。我只想知道这些段的开始结束,因此,它们的长度
  • 这是给定区间的并集,而不是交集。

标签: python intersection


【解决方案1】:

尝试以下操作:

def group(data):
    data = sorted(data)
    it = iter(data)
    a, b = next(it)
    for c, d in it:
        if b >= c:  # Use `if b > c` if you want (1,2), (2,3) not to be
                    # treated as intersection.
            b = max(b, d)
        else:
            yield a, b
            a, b = c, d
    yield a, b


with open('file') as f:
    data = [map(int, line.split()) for line in f]

for a, b in group(data):
    print a, b

例子:

>>> data = (9,16), (1,5), (1,3), (1,2), (3,6), (9,11), (12,17), (2,4),
>>> list(group(data))
[(1, 6), (9, 17)]

【讨论】:

    【解决方案2】:

    以下看起来很有希望。第一部分基于您的方法。第二部分只是在范围的联合中寻找连续的区间。

    intervals = []
    with open('contigous_input.txt', 'r') as infile:
        for line in infile:
            start, stop = sorted(map(int, line.split()))
            intervals.append(range(start, stop+1))
    
    union = list(set().union(*intervals))
    print union
    
    results = []
    i = start = 0
    j = i + 1
    while j < len(union):
        if union[j] != union[i]+1:
            results.append( (union[start], union[j-1]) )
            if j == len(union):
                break
            i = start = j
            j = i + 1
        else:
            i, j = j, j + 1
    
    if start != j-1:
        results.append( (union[start], union[j-1]) )
    
    print results
    

    输出:

    [1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17]
    [(1, 6), (9, 17)]
    

    【讨论】:

      【解决方案3】:

      您应该使用 2 元组而不是 range 函数,因为 range 返回一个 list。如果可能的话,这是一个简单的函数,它将结合你的两个 2 元组:

      def combine_bounds(x, y):
        a, b = sorted([x, y])
        if a[1]+1 >= b[0]:
          return (a[0], max(a[1],b[1]))
      

      样本输出:

      >>> combine_bounds((1,2), (3,4))
      (1, 4)
      >>> combine_bounds((1,100), (3,4))
      (1, 100)
      >>> combine_bounds((1,2), (4,10))
      >>> combine_bounds((1,3), (4,10))
      (1, 10)
      >>> combine_bounds((1,6), (4,10))
      (1, 10)
      >>> combine_bounds((10,600), (4,10))
      (4, 600)
      >>> combine_bounds((11,600), (4,10))
      (4, 600)
      >>> combine_bounds((9,600), (4,10))
      (4, 600)
      >>> combine_bounds((1,600), (4,10))
      (1, 600)
      >>> combine_bounds((12,600), (4,10))
      >>> combine_bounds((12,600), (4,10)) is None
      True
      

      None 在 Python 中是一个错误值,因此您可以在条件句中使用combine_bounds 的结果。如果它返回None(类似于False),那么就没有交集。如果它返回一个2元组,那么就有一个交集,返回值就是结果。

      我并没有为你做所有的工作(你仍然需要弄清楚如何在输入上使用它来获得你想要的输出),但这应该会让你朝着正确的方向前进!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-11
        相关资源
        最近更新 更多