Thursday, July 19, 2012

Combine Ranges of Integers

At one point in an application I needed to be able to combine a range of numbers into a comma-delimited string of ints with the fun added twist of combining all sequential ints together into a range.  Stupid exact matching tool spec.... So instead of writing a new tool to do the same validation check (because I'm crazy but also the other *azy: lazy) I wrote a method to create the combined ranges.

This is in Groovy and quite frankly may be able to be more efficient, but this is what I pounded out that's quick to solve this problem.  Improve if you want!

/**
* Find ranges of continuous numbers in a csv string.
* ex: 1,5,17-20,21,38,39,40,56 -> 1,5,17-21,38-40,56
* @param toConvert string of numbers
*/
static combineRanges(toConvert){
def commaSplit = toConvert.split(/,/)
def all = [commaSplit[0]]
int x = 0
def holding = commaSplit[0]
commaSplit = commaSplit[1..(commaSplit.size()-1)]
commaSplit.each { piece ->
piece = piece.trim()
def holdings = holding.split(/,/)
def tempCheck = holding.isInteger() ? holding.toInteger() : holdings[1].toInteger()
def endCap = piece.isInteger(): piece ? piece.split(/-/)[1]
if(endCap.toInteger() == tempCheck+1){ //add to ranges and keep rolling
holding = "${holdings[0]}-${endCap}"
all[x] = holding
} else { //move to the next range
all[x] = holding
x++
holding = endCap
}
}
//need to append the last value if it wasn't by the service
def lastRegistered = (all[-1].split(/-/).size() > 1) ? all[-1].split(/-/)[1] : all[-1].split(/-/)[0]
def lastHeld = (holding[-1].split(/-/).size() > 1) ? holding[-1].split(/-/)[1] : holding[-1].split(/-/)[0]
if(lastRegistered != lastHeld){
all += holding
}
all.join(',')
}

If you find improvements, feel free to post, all I ask is to please make sure you've tested your code before posting.  Nothing is sadder than getting someone's code from online and then having to debug.  Though it's the easiest thing to blame in your work ;)

</sidebar>


No comments:

Post a Comment