Я вижу вашу точку зрения, и под капотом split
также проводит indexOf
-проверку, чтобы получить соответствующие детали.
Я не знаю ни одной подобной функции, поддерживающей обе операции в одной, хотя такая функция в основном была бы просто аналогична той, что мы уже использовали для private fun split
-осуществления.
Таким образом, если вы действительно хотите и то, и другое за один шаг (и вам требуется эта функциональность чаще), вы можете захотеть реализовать свою собственную splitOrNull
-функцию, в основном копируя текущую (приватную) реализацию split
и адаптируя в основном 3 его части (тип возврата List<String>?
, условие, если indexOf
доставляет -1
, мы просто возвращаем null
; и некоторые значения по умолчанию, чтобы его было легко использовать (ignoreCase=false
, limit=0
); помечены изменения с // added
или // changed
):
fun CharSequence.splitOrNull(delimiter: String, ignoreCase: Boolean = false, limit: Int = 0): List<String>? { // changed
require(limit >= 0, { "Limit must be non-negative, but was $limit." })
var currentOffset = 0
var nextIndex = indexOf(delimiter, currentOffset, ignoreCase)
if (nextIndex == -1 || limit == 1) {
if (currentOffset == 0 && nextIndex == -1) // added
return null // added
return listOf(this.toString())
}
val isLimited = limit > 0
val result = ArrayList<String>(if (isLimited) limit.coerceAtMost(10) else 10)
do {
result.add(substring(currentOffset, nextIndex))
currentOffset = nextIndex + delimiter.length
// Do not search for next occurrence if we're reaching limit
if (isLimited && result.size == limit - 1) break
nextIndex = indexOf(delimiter, currentOffset, ignoreCase)
} while (nextIndex != -1)
result.add(substring(currentOffset, length))
return result
}
Имея такую функцию на месте, вы можете суммировать contains
/ indexOf
и split
в один вызов:
myPairStr.asSequence()
.mapNotNull {
it.splitOrNull("=") // or: it.splitOrNull("=", limit = 2)
}
В противном случае ваш нынешний подход уже достаточно хорош. Вариантом этого будет просто проверить размер разбиения после его разбиения (в основном устраняя необходимость писать contains('=')
и просто проверяя ожидаемый размер, например ::
myPairStr.asSequence()
.map { it.split('=') }
.filter { it.size > 1 }
Если вы хотите разделить $key=$value
-форматы, где value
может содержать дополнительные =
, вы можете вместо этого использовать следующее:
myPairStr.asSequence()
.map { it.split('=', limit = 2) }
.filter { it.size > 1 }
// .associate { (key, value) -> key to value }