我有一个像这样的字符串列表:
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", ...)
我想在它们之间添加一个分隔符“”并限制结果的长度。
通过使用joinToString
和subString
,我可以实现结果。
texts.filter { it.isNotBlank() }
.joinToString(separator = " ")
.substring()
问题是:我只想使用joinToString
并在达到MAX_LENGTH时断开迭代器,因此它不必在此之后执行任何“连接”和subString
。
我怎么能这样做?
首先使用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
在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 }