如何根据右侧字符串中字符总数的限制有条件地连接列表中的字符串?

时间:2019-04-05 12:14:11

标签: scala

我有一个包含一些字符串的列表,并且仅当字符串中的字符长度<=一定限制时,我才想合并/连接字符串。

例如,我们有一个字符串列表:

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!")

concat限制为60,这意味着我们必须先将字符串中的字符长度合并到下一个字符串中,并确保字符长度不超过60。如果合并结果超过60,则不要't合并,仅按原样使用元素/字符串,然后移至下一个元素,然后尝试与下一个元素合并。

因此,如果我们采用上面的列表,

我们可以通过以下方法检查每个字符串中char的长度:

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

由此,我们只能将索引0和1处的字符串连接起来,而将索引2保持原样,而将索引3、4和5处的字符串连接起来。 生成的字符串列表现在应如下所示:

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!")

假设您不知道列表中将要包含多少个字符串,那么实现此功能的好方法是什么。

2 个答案:

答案 0 :(得分:2)

我将这段代码砍在一起:

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!

它使用递归函数从列表的开头(此处为right)中删除元素,并将其收集在参数middle中,直到超出大小为止, 然后将middle附加到结果列表left上,并以新的middle开始,直到right为空。


我希望这会有所帮助。

答案 1 :(得分:0)

在有效的字符串连接方面,concatenate的实现不断寻找符合条件的索引范围(getNext告知下一个子集的起始索引)并将其相加使用StringBuilder并最终产生所有串联的字符串。

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
    }
  }
}