Ian Shiundu
Ian Shiundu

Reputation: 121

How can I concatenate strings in a list conditionally based on the total limit of chars in the string on the right?

I have a list with some strings and I would like to merge/concatenate the strings only if the chars length in the strings are <= a certain limit.

For example we have a List of Strings:

val xs = List("This is a sentence in index0.", "This is a short sentence.", "This is a very very very loooooooooong sentence.", "This is another short sentence.", "Another one.", "The end!")

The concat limit is 60, that means we have to look at the lengths of characters in the string before merging it to the next string and ensuring that the character length does not exceed 60. if the merge result will exceed 60 you don't merge and just take the element/string as is, and move to the next element and try merge with the next.

So if we take our above list,

we can check the length of char in each string by:

xs.map(_.length)
res: List[Int] = List(29, 25, 48, 31, 12, 8)

From that, we can only concatenate strings at index 0 and 1, leave index 2 as is and concatenate strings at index 3, 4 and 5. The resulting List of strings should now look like such:

val result = List("This is a sentence in index0.This is a short sentence.", "This is a very very very loooooooooong sentence.", "This is another short sentence.Another one.The end!")

What's a good way of implementing this assuming you don't know how many strings are going to be on the List.

Upvotes: 0

Views: 786

Answers (2)

Aman Agnihotri
Aman Agnihotri

Reputation: 3023

A bit more on the side of efficient string concatenation, this implementation of concatenate keeps finding the index ranges that fit the criteria (getNext tells the start index of the next subset) and adds them up using StringBuilder and finally yields all concatenated strings.

import scala.annotation.tailrec
import scala.collection.mutable.ListBuffer

object ListConcatenation extends App {
  val xs = List(
    "This is a sentence in index0.",
    "This is a short sentence.",
    "This is a very very very loooooooooong sentence.",
    "This is another short sentence.",
    "Another one.",
    "The end!")

  concatenate(xs, 60).foreach(println)

  def concatenate(values: List[String], limit: Int): List[String] = {
    def getNext(start: Int): Int = {
      @tailrec
      def getNext(sum: Int, index: Int): Int = {
        if (index >= values.length)
          index
        else {
          val next = sum + values(index).length

          if (next > limit)
            index
          else
            getNext(next, index + 1)
        }
      }

      getNext(0, start)
    }

    if (values == null || values.length <= 1)
      values
    else {
      val result = new ListBuffer[String]
      var head = 0

      do {
        val next = getNext(head)

        val builder = new StringBuilder

        (head until next)
          .map(values)
          .foreach(builder.append)

        result += builder.toString()

        head = next
      }
      while (head < values.length)

      result.toList
    }
  }
}

Upvotes: 0

Markus Appel
Markus Appel

Reputation: 3238

I hacked together this piece of code:

val xs = List(
  "This is a sentence in index0.",
  "This is a short sentence.",
  "This is a very very very loooooooooong sentence.",
  "This is another short sentence.",
  "Another one.",
  "The end!")

println(concatLimited(xs, 60))

def concatLimited(list: List[String], limit: Int): List[String] = {
  def concat(left: List[String], middle: String, right: List[String]): List[String] = {
    if (right.isEmpty) {
      left :+ middle
    }
    else {
      if (middle.length + right.head.length < limit) {
        concat(left, middle + right.head, right.tail)
      }
      else {
        concat(left :+ middle, right.head, right.tail)
      }
    }
  }

  if (list.isEmpty) List()
  else concat(List(), list.head, list.tail)
}

Try it out!

It uses a recursive function that removes elements from the head of the list (here: right) and collects them in a parameter middle until it exceeds your size, then it appends middle to a resulting list left and starts off with a new middle, until right is empty.


I hope this helps.

Upvotes: 3

Related Questions