Collections 将int列表折叠到kotlin中的范围列表

Collections 将int列表折叠到kotlin中的范围列表,collections,functional-programming,kotlin,Collections,Functional Programming,Kotlin,我有一个整数列表,需要在不丢失任何信息的情况下压缩为整数范围列表(必须有一种方法来反转此操作) 目前我有: val ints = listOf(8, 9, 45, 48, 49, 60, 61, 61, 62, 63, 3, 4, 5, 4, 5, 6) val out = ints .map { it..it } .fold(mutableListOf(ints[0]..(ints[0] - 1)), { acc, next -&

我有一个整数列表,需要在不丢失任何信息的情况下压缩为整数范围列表(必须有一种方法来反转此操作)

目前我有:

val ints = listOf(8, 9, 45, 48, 49, 60, 61, 61, 62, 63, 3, 4, 5, 4, 5, 6)
val out = ints
        .map { it..it }
        .fold(mutableListOf(ints[0]..(ints[0] - 1)),
                { acc, next ->
                    val prev = acc.last()
                    if (prev.last + 1 == next.first) {
                        acc[acc.lastIndex] = prev.first..next.last
                    } else {
                        acc.add(next)
                    }
                    acc
                }).toList()
正确地产生:

[8..9, 45..45, 48..49, 60..61, 61..63, 3..5, 4..6]
但我的解决方案中有两个方面我不喜欢

  • 由于fold的初始值,它不适用于空列表

  • 这对科特林来说太冗长了。我觉得这个问题可以用更好的方式解决

  • 所以,问题是如何修复1和/或2


    提前谢谢

    我的解决方案看起来没什么不同,但我能够解决您的空列表问题:

    val out = ints.fold(mutableListOf<IntRange>()) { acc, next ->
        acc.apply {
            if(isNotEmpty() && last().endInclusive.inc() == next) {
                this[lastIndex] = this[lastIndex].start .. next
            } else {
                add(next..next)
            }
        }
    }
    
    val out=ints.fold(mutableListOf()){acc,next->
    根据申请{
    if(isNotEmpty()&&last().endInclusive.inc()==next){
    此[lastIndex]=此[lastIndex]。开始..下一步
    }否则{
    添加(下一个..下一个)
    }
    }
    }
    

    它的映射也少了一点,使用apply可以去掉一些冗长的内容,并且在最后必须引用
    acc

    因为你实际上改变了
    acc
    ,并在
    折叠的所有迭代中返回相同的范围列表,所以你可能并不真正需要
    折叠,也就是说,
    forEach
    就足够了

    然后,将每个数字映射到
    it..it
    在这里似乎是多余的

    考虑到上面的两个注意事项,可以得到以下稍微简化的解决方案版本:

    val result = mutableListOf<IntRange>()
    ints.forEach {
        val lastRange = result.lastOrNull()
        if (lastRange?.endInclusive == it - 1)
            result[result.lastIndex] = lastRange.first..it
        else
            result += it..it
    }
    
    val result=mutableListOf()
    弗雷赫国际酒店{
    val lastRange=result.lastOrNull()
    if(lastRange?.endInclusive==it-1)
    result[result.lastIndex]=lastRange.first..it
    其他的
    结果+=它..它
    }
    
    我喜欢它的简化和单一的表达。顺便说一句,与原始命令式循环相比,在循环中使用lambda如何/如果会影响性能?因为
    apply
    是一个,它在循环中的使用不会影响性能。我喜欢您的解决方案。感谢@hotkey提供的宝贵提示。我很难找到答案来接受。选择Todd's作为单一表达式。我知道你的也可以通过
    apply
    进行转换。没问题。虽然我个人认为增加另一个嵌套级别并使接收者隐式地使用
    apply
    可能会降低可读性,但这是基于观点的判断。