2013-02-28 6 views
3

Мне нужно написать код, где у меня есть список диапазонов в Groovy. И мне нужно создать новый список, из которого все диапазоны не перекрываются.Удалить перекрывающиеся диапазоны из списка диапазонов Groovy

Например, если вход: [13..15, 14..16]

я должен быть в состоянии создать список, который имеет либо [13..16] или [13..14, 14..16]

Я бы очень признателен за любую помощь. Я написал следующий код сейчас, но его не работает один бит:

def removeOverlapInRanges(ranges) 
{ 
    def cleanedRanges = [] 
    def overLapFound = false 
    def rangeIsClean = true 
    def test = "ranges" 
    ranges.each 
    { 
     range-> 

     def index = ranges.indexOf(range) 
     while (index < ranges.size() -1) 
     { 
      if (ranges.get(index + 1).disjoint(range) == false) 
      { 
       overLapFound = true 
       rangeIsClean = false 
       def nextRange = ranges.get(index + 1) 
       if (range.from > nextRange.from && range.to < nextRange.to) 
        cleanedRanges.add(range.from..range.to) 
       else if (range.from < nextRange.from && range.to < nextRange.to) 
        cleanedRanges.add(range.from..nextRange.to) 
       else if (range.from > nextRange.from && range.to > nextRange.to) 
        cleanedRanges.add(nextRange.from..range.to) 
      } 
      index = index + 1 
     } 
     if (rangeIsClean) 
      cleanedRanges.add(range) 

     rangeIsClean = true 

     test = test + cleanedRanges 
    } 
    cleanedRanges.add(0, cleanedRanges.get(cleanedRanges.size()-1)) 
    cleanedRanges.remove(cleanedRanges.size() - 1) 
    if (overLapFound) 
     return removeOverlapInRanges(cleanedRanges) 
    else 
     return cleanedRanges 
} 

Я прошел [12..13, 17..19, 18..22,17..19, 22..23, 19..20]

И в ответ я получил [12..13]

Спасибо заранее за любой вклад !!

ответ

4

Я получил это:

List<Range> simplify(List<Range> ranges) { 
    ranges.drop(1).inject(ranges.take(1)) { r, curr -> 
    // Find an overlapping range 
    def ov = r.find { curr.from <= it.to && curr.to >= it.from } 
    if(ov) { 
     ov.from = [ curr.from, ov.from ].min() 
     ov.to = [ curr.to, ov.to ].max() 
     simplify(r) 
    } 
    else { 
     r << curr 
    } 
    } 
} 

def ranges = [ 12..13, 17..19, 18..22, 17..19, 22..23, 19..20 ] 
assert simplify(ranges) == [ 12..13, 17..23 ] 

ranges = [ -2..3, -5..-2 ] 
assert simplify(ranges) == [ -5..3 ] 

ranges = [ 3..1, 1..5 ] 
assert simplify(ranges) == [ 5..1 ] // reversed as first range is reversed 

ranges = [ 1..5, 3..1 ] 
assert simplify(ranges) == [ 1..5 ] 

ranges = [ 1..5, 3..1, -1..-4 ] 
assert simplify(ranges) == [ 1..5, -1..-4 ] 

ranges = [ 1..5, -6..-4, 3..1, -1..-4 ] 
assert simplify(ranges) == [ 1..5, -6..-1 ] 

ranges = [ 1..3, 5..6, 3..5 ] 
assert simplify(ranges) == [ 1..6 ] 

Хотя, вероятно, крайние случаи ... Так что я буду делать немного больше испытаний ...

+0

Спасибо за ваши данные .. – user2119516

0

Следующим с создать простой список ваших уникальный номера:

def ranges = [12..13, 17..19, 18..22,17..19, 22..23,19..20 ]; 
def range = ranges.flatten().unique().sort() 

Вот немного другой подход, который дает некоторые хорошие вспомогательные методы:

def parseToRangeString(range) 
{ 
    String result = ""; 
    range.eachWithIndex{cur,i-> 
     def nex = range[i+1] 
     def start = !result || result.endsWith(",") 
     def cont = cur == nex?.minus(1) 
     if (start && cont) //starting a new section and the next item continues this seq (starting a range = 1,10) 
      result += "$cur-" 
     else if (!cont && nex) //not continuing the seq and there are more nums to process (end with more = 6,8) 
      result += "$cur," 
     else if (!cont && !nex) //not continuing the seq but there are no more nums to process (very end = 11) 
      result += cur 
    } 
    return result 
} 
def toRange(rangeStr) 
{ 
    def ranges = rangeStr.split(",").collect{ 
     def range = it.split("-"); 
     new IntRange(range[0] as int, range[-1] as int) 
    } 
} 
List.metaClass.toRangeString = { 
    parseToRangeString(delegate) 
} 
List.metaClass.toRange = { 
    def rangeStr = parseToRangeString(delegate) 
    toRange(rangeStr) 
} 

def ranges = [12..13, 17..19, 18..22,17..19, 22..23,19..20 ]; 
def list = ranges.flatten().unique().sort() 
assert "12-13,17-23" == list.toRangeString() 
assert [12..13,17..23] == list.toRange(); 
+0

Спасибо, что это помогло мне достичь решения. Благодаря тонну! – user2119516

+0

Добро пожаловать. Не забудьте принять ответ. – purgatory101

Смежные вопросы