2014-04-02 16 views
7

Trong Ruby chúng ta có thể làm điều này:Chuỗi phạm vi trong 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"] 

Trong Scala nếu tôi cố gắng cùng tôi nhận được lỗi:

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

Làm thế nào để có được một loạt các Strings trong Scala?

+5

Một hành vi khá kỳ quặc. Làm thế nào để Ruby xác định bạn muốn dừng lại ở ký tự 'z'? –

+0

Infact '(" aB ".." bZ "). Bản đồ {| x | x} 'biết rằng nó phải dừng lại ở' Z'. '(" a0 ".." b9 "). bản đồ {| x | x} 'biết rằng nó phải dừng lại ở' 9'. Vì vậy, phải có một số phạm vi chữ cái và số mà sức mạnh logic này. – tuxdna

Trả lời

3

Ví dụ này, bạn có thể làm (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" 

Chỉnh sửa theo ý kiến, cảm ơn (nhưng nhận được một chút xấu xí!)

+1

Tôi muốn thêm hạn chế một cái gì đó như 'c1 <- atoz nếu c1 <= 'b'' và nó sẽ phù hợp với điều kiện ban đầu của câu hỏi – n1ckolas

+0

bạn sẽ xem xét sau một giải pháp" sạch hơn "? 'def charval (x: Char, y: Char) = x * 1000 + y' và' cho {c1 <- atoz; c2 <- atoz nếu (charval (c1, c2) <= charval ('b', 'b'))} sản lượng s "$ c1 $ c2" '. Giống như Toán nhưng thay thế "bb" bằng một chuỗi kết thúc khác như "bk" trở nên dễ dàng hơn. Một chút có thể đọc được – mesutozer

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

:)

+6

Đó là lý do tại sao tôi đặt một nụ cười sau mã – ZhekaKozlov

-1

Đây là một khả năng, giả sử các ký tự của bạn có nghĩa là nằm trong phạm vi 'a' đến 'z'. Chức năng intToAlpha không phải là rất đẹp và không đối xứng với alphaToInt, do đó, một trong những có thể đến với một thực hiện tốt hơn.

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

Một phiên bản thay thế:

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

Nó giống như một ma trận 26 * 26 cho mỗi sự kết hợp 2 char, IMAGIN chúng ta có một ma trận (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 for comprehension will do độc đáo:

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

Điều này mang lại một Seq/Vector [Chuỗi] với tất cả các hoán vị mà bạn mong đợi

Các vấn đề liên quan