截断文本以在Scala中进行预览

时间:2014-04-29 06:31:22

标签: string scala

我需要截断文字才能获得预览。预览是〜N字符的文本前缀(但不是更多),它不应该在中间分割单词。

preview("aaa", 10) = "aaa"
preview("a b c", 10) = "a b c"
preview("aaa bbb", 5) = "aaa"
preview("a b ccc", 3) = "a b"

我按如下方式编写了一个函数:

def preview(s:String, n:Int) =
  if (s.length <= n) s else s.take(s.lastIndexOf(' ', n))

你会改变或修复它吗?

现在我正在考虑如何处理文本单词由一个或多个空格(包括\n\t等)而不是单个空格分隔的情况。你将如何改进处理这种情况的功能?

4 个答案:

答案 0 :(得分:8)

以下内容如何:

  def preview(s: String, n: Int) = if (s.length <= n) {
    s
  } else {
    s.take(s.lastIndexWhere(_.isSpaceChar, n + 1)).trim
  }

此功能将:

  • 对于较短或相等的字符串n,返回字符串(无需预览)
  • 否则找到n + 1第一个字符中的最后一个空格字符(这将指示最后一个世界是否被拆分,好像它不是n + 1将是空格字符,否则是非 - 空格字符)并将字符串带到此点

注意:isSpaceChar的使用不仅会提供对空间的支持,还会提供对新行或段落的支持,这是我相信您所追求的(并且您可以将其替换为isWhitespace if你需要更多扩展的单词分隔符。)

答案 1 :(得分:2)

我建议下一个:

- 更新 -

def ellipsize(text : String, max : Int): String = {
  def ellipsize0(s : String): String =
    if(s.length <= max) s
    else {
      val end = s.lastIndexOf(" ")
      if(end == -1) s.take(max)
      else ellipsize0(s.take(end))
    }
  ellipsize0("\\s+".r.replaceAllIn(text, " "))
} 

或您的(已修改):

def preview(str : String, n : Int) = { 
  (s : String) => if (s.length <= n) s else s.take(s.lastIndexOf(' ', n))
}.apply( "\\s+".r.replaceAllIn(str, " "))   

答案 2 :(得分:1)

这个怎么样

def preview(s:String, n:Int) =
  if (s.length <= n) s 
  else s.take(n).takeWhile(_ != ' ')

在此处试试:http://scalafiddle.net/console/a05d886123a54de3ca4b0985b718fb9b

答案 3 :(得分:1)

这似乎有效:

  // find the last word that is not split by n, then take to its end
  def preview(text: String, n: Int): String = 
    text take (("""\S+""".r findAllMatchIn text takeWhile (_.end <= n)).toList match {
      case Nil => n
      case ms  => ms.last.end
    })

另一种选择(双关语),但不喜欢所有空格的输入:

text take (("""\S+""".r findAllMatchIn text takeWhile (m => m.start == 0 || m.end <= n)).toList.last.end min n)

外延上:

object Previewer {
  implicit class `string preview`(val text: String) extends AnyVal {
    // find the last word that is not split by n, then take to its end
    def preview(n: Int): String =
      text take (("""\S+""".r findAllMatchIn text takeWhile (_.end <= n)).toList match {
        case Nil => n
        case ms  => ms.last.end
      })
  }
}

看起来很漂亮:

class PreviewTest {
  import Previewer._

  @Test def shorter(): Unit = {
    assertEquals("aaa", "aaa" preview 10)
  } 
  @Test def spacey(): Unit = {
    assertEquals("a b c", "a b c" preview 10)
  }
  @Test def split(): Unit = { 
    assertEquals("abc", "abc cba" preview 5)
  }   
  @Test def onspace(): Unit = {
    assertEquals("a b", "a b cde" preview 3)
  } 
  @Test def trimming(): Unit = {
    assertEquals("a b", "a b    cde" preview 5)
  } 
  @Test def none(): Unit = {
    assertEquals(" " * 5, " " * 8 preview 5)
  }
  @Test def prefix(): Unit = {
    assertEquals("a" * 5, "a" * 10 preview 5)
  } 
}