Scala中的字符串范围

时间:2014-04-02 12:24:40

标签: scala

在Ruby中我们可以这样做:

$ irb
>> ("aa".."bb").map { |x| x }
=> ["aa", "ab", "ac", "ad", "ae", "af", "ag", "ah", "ai", "aj", "ak", "al", "am", "an", "ao", "ap", "aq", "ar", "as", "at", "au", "av", "aw", "ax", "ay", "az", "ba", "bb"]

在Scala中,如果我尝试相同的操作,我会收到错误:

$ scala
Welcome to Scala version 2.9.1 (OpenJDK 64-Bit Server VM, Java 1.7.0_51).

scala> ("aa" to "bb").map(x => x)
<console>:8: error: value to is not a member of java.lang.String
              ("aa" to "bb").map(x => x)
                    ^

如何在Scala中获取一系列字符串?

5 个答案:

答案 0 :(得分:3)

对于这个例子你可以做(​​scala 2.10)

val atoz = 'a' to 'z'
for {c1 <- atoz if c1 <= 'b'; c2 <- atoz if (c1 == 'a' || (c1 == 'b' && c2 < 'c'))} yield s"$c1$c2"

根据评论编辑,谢谢(但有点难看!)

答案 1 :(得分:2)

理解能做得很好:

val abc = 'a' to 'z'
for (c1 <- abc; c2 <- abc) yield (s"$c1$c2")

这会产生一个Seq / Vector [String],其中包含您期望的所有排列

答案 2 :(得分:1)

('a' to 'z').map("a" + _) :+ "ba" :+ "bb"

:)

答案 3 :(得分:-1)

这是一种可能性,假设你的角色应该在范围内&#39; a&#39;到了&#39;。 intToAlpha函数不是很漂亮,与alphaToInt不对称,因此可以提供更好的实现。

// "a" -> 0, "b" -> 1, "ba" -> 26, "bb" -> 27 etc.
def alphaToInt(s: String) = (0 /: s) { (res, c) => res * 26 + c - 'a' }

// reverse function to `alphaToInt`
def intToAlpha(len: Int)(i: Int) = {
  val sb  = new StringBuilder
  var j   = i
  while (sb.length < len) {
    sb append ((j % 26) + 'a').toChar
    j /= 26
  }
  sb.reverse.toString
}

def range(from: String, to: String) =
  alphaToInt(from) to alphaToInt(to) map intToAlpha(from.length)

测试:

range("aa", "bb")

替代版本:

import annotation.tailrec

@tailrec def intToAlpha(len: Int, res: String = "")(i: Int): String =
  if (len <= 0) res
  else {
    val c = ((i % 26) + 'a').toChar
    intToAlpha(len - 1, s"$c$res")(i / 26)
  }

答案 4 :(得分:-1)

对于每2个字符组合,它就像一个26 * 26矩阵,想象我们有一个矩阵(a-z * a-z):

def scan(start:String, end:String) = { 

  val row_start                 = start.toCharArray.head
  val column_start_of_first_row = start.toCharArray.last
  val row_end                   = end.toCharArray.head
  val column_end_of_last_row    = end.toCharArray.last

  val printRow =
    (current_row:String, current_row_start_col:Char, current_row_end_col:Char) =>
      (current_row_start_col to current_row_end_col).map( current_row + _ ) 

  (row_start to row_end).map { current_row=>
      current_row match {
        case `row_start` => printRow(current_row.toString, column_start_of_first_row, 'z')
        case `row_end`   => printRow(current_row.toString, 'a'                      , column_end_of_last_row)
        case _           => printRow(current_row.toString, 'a'                      , 'z')                                                                                      
      }   
  }.reduce(_ ++: _)

}

println( scan("aa", "bb") )
println( scan("af", "bb") )