2014-04-02 14 views
7

In Ruby wir dies tun können:String Bereich in Scala

$ 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"] 

In Scala, wenn ich das gleiche versuche ich Fehler:

$ 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) 
        ^

Wie eine Reihe von Strings in Scala bekommen?

+5

Ein etwas ausgefallenes Verhalten erwarten würde. Wie bestimmt Ruby, dass du beim Zeichen "z" aufhören willst? –

+0

Infact '(" aB ".." bZ "). Map {| x | x} 'weiß, dass es bei' Z' stehen bleiben muss. '(" a0 ".." b9 "). map {| x | x} 'weiß, dass es bei' 9' aufhören muss. Also müssen einige alphabetische und numerische Bereiche vorhanden sein, die diese Logik antreiben. – tuxdna

Antwort

3

Für dieses Beispiel Sie (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" 

Herausgegeben per Kommentar tun können, dank (aber ein bisschen hässlich! Bekommen)

+1

Ich würde eine Einschränkung hinzufügen wie 'c1 <- atoz wenn c1 <= 'b'' und es würde den Anfangsbedingungen der Frage – n1ckolas

+0

entsprechen. Würden Sie eine" sauberere "Lösung in Betracht ziehen? 'def charval (x: Zeichen, y: Zeichen) = x * 1000 + y 'und' für {c1 <- atoz; c2 <- atoz if (charval (c1, c2) <= charval ('b', 'b'))} ergibt s "$ c1 $ c2" '. Mehr wie Mathe, aber das Ersetzen von "bb" durch eine andere Endzeichenfolge wie "bk" wird einfacher. Ein bisschen besser lesbar – mesutozer

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

:)

+6

Deshalb lege ich ein Lächeln nach dem Code – ZhekaKozlov

-1

Hier eine Möglichkeit, vorausgesetzt, Ihre Charaktere sollen im Bereich von 'a' bis 'z' liegen. Die intToAlpha Funktion ist nicht sehr hübsch und nicht symmetrisch zu alphaToInt, so könnte man mit einer besseren Implementierung kommen.

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

Test:

range("aa", "bb") 

Eine alternative Version:

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

Es ist wie eine 26 * 26 Matrix für jede 2 char Kombination, imagin haben wir eine Matrix (az * az) :

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

A zum Verständnis würde tun schön:

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

Dies ergibt eine Seq/Vector [Zeichenfolge] mit allen Permutationen Sie