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

时间:2018-05-02 22:05:28

标签: collections functional-programming kotlin

我有一个需要压缩到int范围列表的整数列表,而不会丢失任何信息(必须有一种方法可以反转此操作)。

目前我有:

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]

我的解决方案中有两个方面我不喜欢,

  1. 由于fold的初始值

  2. ,它不适用于空列表
  3. kotlin非常详细。我觉得这可以通过更好的方式解决。

  4. 那么,问题是如何修复1和/或2?

    提前致谢!

2 个答案:

答案 0 :(得分:2)

由于您实际变异acc并在fold的所有迭代中返回相同的范围列表,因此您可能不需要fold,即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
}

答案 1 :(得分:1)

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

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)
        }
    }
}

它的映射也有点少,使用apply会消除一些冗长,最后不得不引用acc