Reputation: 121
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
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
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)
}
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