Skip to content

Instantly share code, notes, and snippets.

@Kalaiz
Last active December 5, 2020 05:19
Show Gist options
  • Save Kalaiz/c05749912dfbe5c554f9b99f7677eebc to your computer and use it in GitHub Desktop.
Save Kalaiz/c05749912dfbe5c554f9b99f7677eebc to your computer and use it in GitHub Desktop.
Split Kotlin List<String> using Delimiter Testing
/* https://stackoverflow.com/questions/65140871/split-list-when-predicate-is-true*/
/* First Way */
inline fun List<String>.splitWhenOne(predicate: (String)->Boolean):List<List<String>> {
val list = mutableListOf<MutableList<String>>()
var needNewList = false
forEach {
string->
if(!predicate(string)){
if(needNewList||list.isEmpty()){
list.add(mutableListOf(string))
needNewList= false
}
else {
list.last().add(string)
}
}
else {
/* When a delimiter is found */
needNewList = true
}
}
return list
}
/* Second Way */
inline fun List<String>.splitWhenTwo(predicate: (String)->Boolean):List<List<String>> {
val list = mutableListOf<List<String>>()
withIndex()
.filter { indexedValue -> predicate(indexedValue.value) || indexedValue.index==0 || indexedValue.index==size-1} // Just getting the delimiters with their index; Include 0 and last -- so to not ignore it while pairing later on
.zipWithNext() // zip the IndexValue with the adjacent one so to later remove continuous delimiters; Example: Indices : 0,1,2,5,7 -> (0,1),(1,2),(2,5),(5,7)
.filter { pair-> pair.first.index + 1 != pair.second.index } // Getting rid of continuous delimiters; Example: (".",".") will be removed, where "." is the delimiter
.forEach{pair->
val startIndex = if(predicate(pair.first.value)) pair.first.index+1 else pair.first.index // Trying to not consider delimiters
val endIndex = if(!predicate(pair.second.value) && pair.second.index==size-1) pair.second.index+1 else pair.second.index // subList() endIndex is exclusive
list.add(subList(startIndex,endIndex)) // Adding the relevant sub-list
}
return list
}
/* Third Way */
inline fun List<String>.splitWhenThree(predicate: (String)-> Boolean):List<List<String>> =
foldIndexed(mutableListOf<MutableList<String>>(),{index, list, string->
when {
predicate(string) -> if(index<size-1 && !predicate(get(index+1))) list.add(mutableListOf()) // Adds a new List within the output List; To prevent continuous delimiters -- !predicate(get(index+1))
list.isNotEmpty() -> list.last().add(string) // Just adding it to lastly added sub-list, as the string is not a delimiter
else -> list.add(mutableListOf(string)) // Happens for the first String
}
list})
fun main(){
val testCase = listOf(
"This is", "the", "first sentence", ".",
"And", "now there is", "a second", "one", ".",
"Nice","."
)
val testCaseTwo = listOf(
".",".","This is", "the", "first sentence", ".",
"And", "now there is", "a second", "one", ".",
"Nice",".",".",".",".",".","."
)
val testCaseThree = listOf(
"|",".","This is", "the", "first sentence", ".",
"And", "now there is", "a second", "one", "|",
"this"," the third","|",
"this","/","the","last"
)
/*
* The following two tests should yield the result
* listOf(
* listOf("This is", "the", "first sentence"),
* listOf("And", "now there is", "a second", "one"),
* listOf("Nice")
* )
*/
println("Test Case One")
testAll(testCase,".")
println()
println("Test Case Two")
testAll(testCaseTwo,".")
/*
* The following test should be the result of the transformation
* listOf(
* listOf(".",This is", "the", "first sentence","." ."And", "now there is", "a second", "one"),
* listOf("this","the third"),
* listOf("this","/","the","last")
* )
*/
println()
println("Test Case Three")
testAll(testCaseThree,"|") // Note Delimiter is "|"
}
fun testAll(list:List<String>,delimiter:String){
println( list.splitWhenOne {it==delimiter } )
println( list.splitWhenTwo {it==delimiter } )
println( list.splitWhenThree {it==delimiter } )
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment