在Kotlin中添加限制joinToString的条件

问题描述 投票:2回答:2

我有一个像这样的字符串列表:

val texts = listOf("It is a",
                "long established fact that a reader will be distracted,",
                "by the readable content of a page when looking at its layout.",
                "The point of using Lorem Ipsum is that it has a more-or-less normal",
                "distribution of letters, as opposed to using, making it look like readable English.",
                " Many desktop publishing packages and web page,",
                "editors now use Lorem Ipsum as their default model text, and a search,",
                "for \'lorem ipsum\' will uncover many web sites still in their infancy",
                "Various versions have evolved over the years", ...)

我想在它们之间添加一个分隔符“”并限制结果的长度。

通过使用joinToStringsubString,我可以实现结果。

texts.filter { it.isNotBlank() }
                .joinToString(separator = " ")
                .substring()

问题是:我只想使用joinToString并在达到MAX_LENGTH时断开迭代器,因此它不必在此之后执行任何“连接”和subString

我怎么能这样做?

java android list kotlin
2个回答
2
投票

首先使用takeWhile来限制总长度,然后使用join

fun main(args: Array<String>) {
    val texts = listOf("It is a",
            "long established fact that a reader will be distracted,",
            "by the readable content of a page when looking at its layout.",
            "The point of using Lorem Ipsum is that it has a more-or-less normal",
            "distribution of letters, as opposed to using, making it look like readable English.",
            " Many desktop publishing packages and web page,",
            "editors now use Lorem Ipsum as their default model text, and a search,",
            "for \'lorem ipsum\' will uncover many web sites still in their infancy",
            "Various versions have evolved over the years")

    val limit = 130
    var sum = 0
    val str = texts.takeWhile { sum += it.length + 1;  sum <= limit }.joinToString(" ")

    println(str)
    println(str.length)
}

将打印

It is a long established fact that a reader will be distracted, by the readable content of a page when looking at its layout.
125

2
投票

limit中使用joinToString参数

val substring = texts.filter { it.isNotBlank() }
                .joinToString(separator = " ", limit = 10, truncated = "")
                .substring(0)

注意truncated参数,以避免...后缀。

由于原始答案寻找MAX_LENGTH作为最终字符串长度以上解决方案将无法正常工作。理想的一个是takeWhile,如公认的答案。但它需要依赖外部变量。如果可以的话,我宁愿使用功能方法,但似乎没有。所以基本上我们需要使用谓词减少操作,因此reduce的稍微改变版本将起作用

public inline fun <S, T : S> Iterable<T>.reduceWithPredicate(operation: (acc: S, T) -> S, predicate: (S) -> Boolean): S {
        val iterator = this.iterator()
        if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
        var accumulator: S = iterator.next()
        while (iterator.hasNext() && predicate(accumulator)) {
            accumulator = operation(accumulator, iterator.next())
        }
        return accumulator
    }

由于我们正在处理字符串连接并试图限制其长度,我们必须使用substring来获得精确的长度,但是在内联函数上方,eleminates连接所有元素并且不需要像takeWhile中的中间列表。也有点改变版本的takeWhile会起作用

val joinedString = texts.filter { it.isNotBlank() }
                .reduceWithPredicate({ s1, s2 -> "$s1 $s2" }, { it.length < 100 })
                .substring(100)
assertTrue { joinedString.length < 100 }
© www.soinside.com 2019 - 2024. All rights reserved.