Home > Software engineering >  Is There a Best Way to Chunk a String from the last element to first
Is There a Best Way to Chunk a String from the last element to first

Time:07-14

Is there a good or best way to add some leading zeros for the string chunk that don't have an appropriate number of digits. At the code below I want to split a string where each chunk is composed of 4 digits.

To add some leading zeros to a string I use this approach:

val text = "1010111".reversed()  // 1110101 | len: 7
  .chunked(4) {  // [1110, 101 *this element only gets 3 digits]
    val sb = StringBuilder(it)
    val rem = it.length % 4  // 3

    /* [1110, 1010 -> now this element have a same digits w...] */
    if (rem != 0) sb.append("0".repeat(4 - rem)).toString()

  } // result: [1110, 1010]
  .reversed() // [1010, 1110]
  .map { it.reversed } // [0101, 0111]

val result = text.joinToString("")
println("""
   before: $text    /*  101 0111 */
   after : $result  /* 0101 0111 */
""".trimIndent())

CodePudding user response:

This would probably be the simplest approach:

val text  = "1010111"

val result = text
    .reversed()
    .chunked(4)
    .joinToString("") { it.padStart(4, '0') }
    .reversed()

reverse() does what the name implies

chunked(4) gives us multiple list with 4 elements each. The last list might have less than 4 if the initial text is not divisible by 4

joinToString("") let's us put the thing together, while also applying the next modifier:

it.padStart(4, '0') adds as many '0' as necessary in order for the current chunk to be 4 characters long (basically it will only add to the final chunk

reverse() returns our text back in the correct order.

CodePudding user response:

I would suggest:

    val text = "1010111" // len: 7
    val zerosToAdd = (4 - text.length % 4).takeIf { it != 4 } ?: 0 // 1
    val result = "0".repeat(zerosToAdd)   text // result = 01010111

CodePudding user response:

chunked can also take a second argument, a function in which you can transform the chunk. In this case it needs to be reversed and then in the let lambda leading zeros can be prepended with padStart:

val text = "1010111"

val result = text
  .reversed()
  .chunked(4) { chunk -> chunk.let { if (it.length < 4) it.padEnd(4, '0') else it } }
  .reversed()
  .joinToString("") { it.reversed() }

println(result)   // Output: [0101, 0111]

CodePudding user response:

An alternative to reversing the string and chunking it and pad the last element and reverse back, would be to just calculate the padding needed at the beginning of the string:

fun String.padStartWithZerosToMultipleOf(value: Int): String {
  return this.padStart(length.div(value) * value   length.rem(value).let { if (it == 0) 0 else value }, '0')
}

val text = "1010111"

val result = text.padStartWithZerosToMultipleOf(4)

println(result)
  • Related