如何将整数序列拆分为范围(java \ kotlin)

时间:2016-07-20 12:34:03

标签: java kotlin

现在我有一个像这样的序列

("1,3,5,7,11,13,15,17,21,23,25,27,29,33,35")

如何分成不间断范围。例如,我需要得到奇数范围的列表,如下所示:

([1,3,5,7] [11,13,15,17] [21,23,25,27,29] [33,35])

UPD。我的代码:

fun test1 (arr : List<Int>): List<List<Int>>{
        var lastElem: Int? = null
        val arr = ArrayList(arr)
        Collections.sort(arr)
        val iter = arr.iterator()
        val resultList = ArrayList<List<Int>>()
        val tmlList = ArrayList<Int>()
        while(iter.hasNext()){
            val currElem = iter.next()
            if (lastElem == null) {
                lastElem = currElem
                tmlList.add(currElem)
            }else if(lastElem+2==currElem){
                tmlList.add(currElem)
                lastElem = currElem
            }else if(lastElem+2 != currElem){
                resultList.add(ArrayList(tmlList))
                tmlList.clear()
                tmlList.add(currElem)
                lastElem = currElem
            }
        }
        resultList.add(ArrayList(tmlList))
        return resultList;
}

UPD。我很抱歉代码。我添加了我的解决方案版本。我正在寻找一个更漂亮的版本。

2 个答案:

答案 0 :(得分:4)

您可以使用RangeSet中的google/guava: Google Core Libraries for Java 6+

val rangeSet: RangeSet<Int> = ImmutableRangeSet.builder<Int>()
        .apply { sequence.forEach { add(Range.closedOpen(it, it + 2)) } }
        .build()
val nonBreakingRanges = rangeSet.asRanges()
        .map { ContiguousSet.create(it, DiscreteDomain.integers()).filter { it % 2 != 0 } }

您可以使用fold

val nonBreakingRanges = sequence.fold(mutableListOf<MutableList<Int>>()) {
    nonBreakingRanges, element ->
    val lastRange = nonBreakingRanges.lastOrNull()
    if (lastRange != null && lastRange.lastOrNull() == element - 2) {
        lastRange.add(element)
    } else {
        nonBreakingRanges.add(mutableListOf(element))
    }
    nonBreakingRanges
}

您可以使用groupBy

var previousElement: Int? = null
var rangeIndex = 0
fun rangeIndexSelector(currentElement: Int): Int {
    if (previousElement != currentElement - 2) {
        rangeIndex++
    }
    previousElement = currentElement
    return rangeIndex
}

val nonBreakingRanges = sequence.groupBy(::rangeIndexSelector).values

答案 1 :(得分:1)

这是使用maplet的一种方式:

val a = ("1,3,5,7,11,13,15,17,21,23,25,27,29,33,35")
val nonBreakingRanges = a.split(',')
    .map { it.toLong() }
    .let { list ->
        var lastRange = mutableListOf<Long>()
        list.map {
            val previousElement = lastRange.lastOrNull() ?: it
            if (it == previousElement + 2) {
                lastRange.add(it)
            } else {
                lastRange = mutableListOf(it)
            }
            lastRange
        }.distinct()
    }