I came across an issue the other day where I really just could not think of a functional solution. So I fell back on my imperative programming skills. Since a functional solution still eludes me, I figured I'd shout out for some help here.
Use Case
I have a List of Strings with arbitrary lengths. These Strings need to be combined into rows that have the same max length.
When a single String's length is greater than max length, that String just gets it's own row as each row eventually get's handled by a function that ensures all Strings are truncated to an appropriate length.
Example Usage
scala> val rows = combineStrings(List("Short", "This is a particularly long String...", "More", "Small", "Strings"), 35)
Current Output
scala> rows.foreach(println)
Short
This is a particularly long String...
More, Small, Strings
Desired Output
scala> rows.foreach(println)
Short, More, Small, Strings
This is a particularly long String...
Current Solution
def combineStrings(strs: List[String], maxLen: Int)
: List[String] = {
import scala.collection.mutable.ListBuffer
var scratch = strs.mkString("|")
val rows = ListBuffer[String]()
while (scratch.length > 1) {
scratch.indexOf("|") match {
case idx if (idx == -1 || scratch.length < maxLen) =>
rows += scratch
scratch = ""
case idx if idx > maxLen =>
rows += scratch.substring(0, idx)
scratch = scratch.substring(idx+1)
case idx =>
val lIdx = scratch.lastIndexOf("|", maxLen)
rows += scratch.substring(0, lIdx)
scratch = scratch.substring(lIdx+1)
}
}
rows.toList.map(_.replaceAll("\\|", ", "))
}
Notes
- Pipes are used because the original Strings are more likely to have their own commas than their own pipes. Maybe other solutions won't need this hackery.
- Strings are kept in the same order, but in the end I'd prefer to have the most "compact" rows possible.
Summary
Any ideas on how to make this more functional would be greatly appreciated. I found several functions in Scala's "String" that looked promising, but I'm not really sure how to integrate them with the length requirements.
", "
) such that the combined string has length under and as close tomaxLength
as possible without splitting the strings. Furthermore if a string is already overmaxLength
then it is left. Yes? Please clarify (1) do the joined strings have to be undermaxLength
or 'minimally over'? (2) is this an optimization problem - i.e. should the joined length be as close as possible tomaxLength
(3) is order important? \$\endgroup\$