【问题标题】:Scala: Print separators when using output streamScala:使用输出流时打印分隔符
【发布时间】:2012-12-03 05:34:50
【问题描述】:

当我们需要串联一个字符串数组时,可以使用 mkString 方法:

val concatenatedString = listOfString.mkString

但是,当我们有一个很长的字符串列表时,连接字符串可能不是一个好的选择。在这种情况下,直接打印到输出会更合适,将其写入输出流很简单:

listOfString.foreach(outstream.write _)

但是,我不知道附加分隔符的巧妙方法。我尝试过的一件事是使用索引循环:

var i = 0
for(str <- listOfString) {
  if(i != 0) outstream.write ", "
  outstream.write str
  i += 1
}

这行得通,但它太罗嗦了。虽然我可以让一个函数封装上面的代码,但我想知道 Scala API 是否已经有一个函数可以做同样的事情。

谢谢。

【问题讨论】:

    标签: scala


    【解决方案1】:

    这是一个以更优雅的方式做你想做的事情的函数:

    def commaSeparated(list: List[String]): Unit = list match {
        case List() => 
        case List(a) => print(a)
        case h::t => print(h + ", ")
                     commaSeparated(t)
    }
    

    递归避免了可变变量。

    为了让它更具功能性风格,你可以传入你想在每个项目上使用的函数,即:

    def commaSeparated(list: List[String], func: String=>Unit): Unit = list match {
        case List() => 
        case List(a) => func(a)
        case h::t => func(h + ", ")
                     commaSeparated(t, func)
    }
    

    然后调用它:

    commaSeparated(mylist, oustream.write _)
    

    【讨论】:

      【解决方案2】:

      我相信您想要的是 mkString 的重载定义。

      mkString的定义:

      scala> val strList = List("hello", "world", "this", "is", "bob")
      strList: List[String] = List(hello, world, this, is, bob)
      

      def mkString: String

      scala> strList.mkString
      res0: String = helloworldthisisbob
      

      def mkString(sep: String): String

      scala> strList.mkString(", ")
      res1: String = hello, world, this, is, bob  
      

      def mkString(start: String, sep: String, end: String): String

      scala> strList.mkString("START", ", ", "END")
      res2: String = STARThello, world, this, is, bobEND
      

      编辑 这个怎么样?

      scala> strList.view.map(_ + ", ").foreach(print) // or .iterator.map
      hello, world, this, is, bob,
      

      【讨论】:

      • 另外,有时使用mkString(firstDel, del, lastDel)也很有用
      • 不,我要做的是直接写入输出流,而不是连接字符串,因为我有很长的列表要连接。
      • 已编辑,这是你想要的吗?
      • 谢谢,但尾随额外的逗号“,”在某些上下文中会产生问题。
      • 是的,这是我在原始问题中所做的。我想问的是开箱即​​用的功能,可以在一行中执行此操作。
      【解决方案3】:

      不适合并行化代码,否则:

      val it = listOfString.iterator
      it.foreach{x => print(x); if (it.hasNext) print(' ')}
      

      【讨论】:

        【解决方案4】:

        这是另一种避免 var 的方法

        listOfString.zipWithIndex.foreach{ case (s, i) =>
            if (i != 0) outstream write ","
            outstream write s }
        

        【讨论】:

          【解决方案5】:

          自我回答

          我写了一个函数封装了原问题中的代码:

          implicit def withSeparator[S >: String](seq: Seq[S]) = new {
            def withSeparator(write: S => Any, sep: String = ",") = {
              var i = 0
              for (str <- seq) {
                if (i != 0) write(sep)
                write(str)
                i += 1
              }
              seq
            }
          }
          

          你可以这样使用它:

          listOfString.withSeparator(print _)
          

          分隔符也可以赋值:

          listOfString.withSeparator(print _, ",\n")
          

          谢谢大家回答我。我想使用的是简洁且不太慢的表示。 withSeparator 的隐式函数看起来像我想要的东西。所以我接受我自己对这个问题的回答。再次感谢。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-05-10
            • 1970-01-01
            • 2011-09-17
            • 1970-01-01
            • 2016-03-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多