복붙노트

[PYTHON] 여러 범위의 파이썬 공용체

PYTHON

여러 범위의 파이썬 공용체

나는이 범위를 가지고있다.

7,10
11,13
11,15
14,20
23,39

중첩되지 않는 범위를 제공하기 위해 겹치는 범위의 합집합을 수행해야합니다. 예에서 다음과 같습니다.

7,20
23,39

루비에서 배열의 범위의 시작과 끝을 밀고 정렬 한 다음 겹치는 범위의 결합을 수행합니다. 파이썬에서 이것을하는 빠른 방법?

감사

해결법

  1. ==============================

    1.예를 들어, (7, 10)과 (11, 13)은 (7, 13)의 결과를 얻습니다.

    예를 들어, (7, 10)과 (11, 13)은 (7, 13)의 결과를 얻습니다.

    a = [(7, 10), (11, 13), (11, 15), (14, 20), (23, 39)]
    b = []
    for begin,end in sorted(a):
        if b and b[-1][1] >= begin - 1:
            b[-1] = (b[-1][0], end)
        else:
            b.append((begin, end))
    

    지금은 b입니다.

    [(7, 20), (23, 39)]
    

    편집하다:

    @CentAu가 올바르게 고지하기 때문에 [(2,4), (1,6)]은 (1,6) 대신 (1,4)를 반환합니다. 다음은이 케이스를 올바르게 처리 한 새 버전입니다.

    a = [(7, 10), (11, 13), (11, 15), (14, 20), (23, 39)]
    b = []
    for begin,end in sorted(a):
        if b and b[-1][1] >= begin - 1:
            b[-1][1] = max(b[-1][1], end)
        else:
            b.append([begin, end])
    
  2. ==============================

    2.이전 질문. 그러나 나는 미래의 참고 문헌을 위해이 대답을 덧붙이고 싶었다. sympy를 사용하여 구간의 합집합을 얻을 수 있습니다.

    이전 질문. 그러나 나는 미래의 참고 문헌을 위해이 대답을 덧붙이고 싶었다. sympy를 사용하여 구간의 합집합을 얻을 수 있습니다.

    from sympy import Interval, Union
    def union(data):
        """ Union of a list of intervals e.g. [(1,2),(3,4)] """
        intervals = [Interval(begin, end) for (begin, end) in data]
        u = Union(*intervals)
        return [list(u.args[:2])] if isinstance(u, Interval) \
           else list(u.args)
    

    Union의 출력이 두 개 이상의 간격 인 경우 Union 오브젝트가 있고 한 개의 간격이있는 경우 출력은 Interval 오브젝트입니다. 이것이 리턴 라인의 if 문에 대한 이유입니다.

    예 :

    In [26]: union([(10, 12), (14, 16), (15, 22)])
    Out[26]: [[10, 12], [14, 22]]
    
    In [27]: union([(10, 12), (9, 16)])
    Out[27]: [[9, 16]]
    
  3. ==============================

    3.나는 (45, 46)과 (45, 45) (11,6)의 존재, (-1, -5)의 존재, (-9, 5)의 존재, (-3, 10)의 존재 등 응용 프로그램에서 발생할 가능성이없는 테스트 사례가 포함됩니다. 어쨌든이 모든 경우에 결과가 옳습니다.

    나는 (45, 46)과 (45, 45) (11,6)의 존재, (-1, -5)의 존재, (-9, 5)의 존재, (-3, 10)의 존재 등 응용 프로그램에서 발생할 가능성이없는 테스트 사례가 포함됩니다. 어쨌든이 모든 경우에 결과가 옳습니다.

    알고리즘 :

    def yi(li):
        gen = (x for a,b in li for x in xrange(a,b+1))
        start = p = gen.next()
        for x in gen:
            if x>p+2:
                yield (start,p)
                start = p = x
            else:
                p = x
        yield (start,x)
    

    다음 코드에서 aff가 True로 설정되면 실행 단계가 표시됩니다.

    def yi(li):
        aff = 0
        gen = (x for a,b in li for x in xrange(a,b+1))
        start = p = gen.next()
        for x in gen:
            if aff:
                print ('start %s     p %d  p+2 %d     '
                       'x==%s' % (start,p,p+2,x))
            if x>p+2:
                if aff:
                    print 'yield range(%d,%d)' % (start,p+1)
                yield (start,p)
                start = p = x
            else:
                p = x
        if aff:
            print 'yield range(%d,%d)' % (start,x+1)
        yield (start,x)
    
    
    
    for li in ([(7,10),(23,39),(11,13),(11,15),(14,20),(45,46)],
               [(7,10),(23,39),(11,13),(11,15),(14,20),(45,46),(45,45)],
               [(7,10),(23,39),(11,13),(11,15),(14,20),(45,45)],
    
               [(7,10),(23,39),(11,13),(11,6),(14,20),(45,46)], 
               #1 presence of (11, 6)
               [(7,10),(23,39),(11,13),(-1,-5),(14,20),(45,45)], 
               #2  presence of (-1,-5)
               [(7,10),(23,39),(11,13),(-9,-5),(14,20),(45,45)], 
               #3  presence of (-9, -5)
               [(7,10),(23,39),(11,13),(-3,10),(14,20),(45,45)]): 
               #4  presence of (-3, 10)
    
        li.sort()
        print 'sorted li    %s'%li
        print '\n'.join('  (%d,%d)   %r' % (a,b,range(a,b)) 
                         for a,b in li)
        print 'list(yi(li)) %s\n' % list(yi(li))
    

    결과

    sorted li    [(7, 10), (11, 13), (11, 15), (14, 20),
                  (23, 39), (45, 46)]
      (7,10)   [7, 8, 9]
      (11,13)   [11, 12]
      (11,15)   [11, 12, 13, 14]
      (14,20)   [14, 15, 16, 17, 18, 19]
      (23,39)   [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 
                 35, 36, 37, 38]
      (45,46)   [45]
    list(yi(li)) [(7, 20), (23, 39), (45, 46)]
    
    sorted li    [(7, 10), (11, 13), (11, 15), (14, 20), 
                  (23, 39), (45, 45), (45, 46)]
      (7,10)   [7, 8, 9]
      (11,13)   [11, 12]
      (11,15)   [11, 12, 13, 14]
      (14,20)   [14, 15, 16, 17, 18, 19]
      (23,39)   [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
                 35, 36, 37, 38]
      (45,45)   []
      (45,46)   [45]
    list(yi(li)) [(7, 20), (23, 39), (45, 46)]
    
    sorted li    [(7, 10), (11, 13), (11, 15), (14, 20), 
                  (23, 39), (45, 45)]
      (7,10)   [7, 8, 9]
      (11,13)   [11, 12]
      (11,15)   [11, 12, 13, 14]
      (14,20)   [14, 15, 16, 17, 18, 19]
      (23,39)   [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
                 35, 36, 37, 38]
      (45,45)   []
    list(yi(li)) [(7, 20), (23, 39), (45, 45)]
    
    sorted li    [(7, 10), (11, 6), (11, 13), (14, 20), 
                  (23, 39), (45, 46)]
      (7,10)   [7, 8, 9]
      (11,6)   []
      (11,13)   [11, 12]
      (14,20)   [14, 15, 16, 17, 18, 19]
      (23,39)   [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 
                 35, 36, 37, 38]
      (45,46)   [45]
    list(yi(li)) [(7, 20), (23, 39), (45, 46)]
    
    sorted li    [(-1, -5), (7, 10), (11, 13), (14, 20), 
                  (23, 39), (45, 45)]
      (-1,-5)   []
      (7,10)   [7, 8, 9]
      (11,13)   [11, 12]
      (14,20)   [14, 15, 16, 17, 18, 19]
      (23,39)   [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
                 35, 36, 37, 38]
      (45,45)   []
    list(yi(li)) [(7, 20), (23, 39), (45, 45)]
    
    sorted li    [(-9, -5), (7, 10), (11, 13), (14, 20), 
                  (23, 39), (45, 45)]
      (-9,-5)   [-9, -8, -7, -6]
      (7,10)   [7, 8, 9]
      (11,13)   [11, 12]
      (14,20)   [14, 15, 16, 17, 18, 19]
      (23,39)   [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
                 35, 36, 37, 38]
      (45,45)   []
    list(yi(li)) [(-9, -5), (7, 20), (23, 39), (45, 45)]
    
    sorted li    [(-3, 10), (7, 10), (11, 13), (14, 20), 
                  (23, 39), (45, 45)]
      (-3,10)   [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      (7,10)   [7, 8, 9]
      (11,13)   [11, 12]
      (14,20)   [14, 15, 16, 17, 18, 19]
      (23,39)   [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 
                 35, 36, 37, 38]
      (45,45)   []
    list(yi(li)) [(-3, 20), (23, 39), (45, 45)]
    
  4. ==============================

    4.

    def range_overlap_adjust(list_ranges):
        overlap_corrected   =   []
        for start, stop in sorted(list_ranges):
            if  overlap_corrected and start-1 <= overlap_corrected [-1][1] and stop >= overlap_corrected [-1][1]:
                overlap_corrected [-1] = min(overlap_corrected [-1][0], start), stop
            elif overlap_corrected and start <= overlap_corrected [-1][1] and stop <= overlap_corrected [-1][1]:
                break
            else:
                overlap_corrected.append((start,stop))
        return overlap_corrected
    
    list_ranges = [(7, 10), (11, 13), (11, 15), (14, 20), (23, 39)]   
    
    
    print range_overlap_adjust(list_ranges)
    
  5. from https://stackoverflow.com/questions/15273693/python-union-of-multiple-ranges by cc-by-sa and MIT license