2015-02-28 24 views
13

Tôi là người mới đến ngôn ngữ lập trình hàm và tôi đang học nó ở Scala cho một dự án đại học. Điều này có vẻ đơn giản, nhưng tôi không thể tìm thấy đủ trợ giúp trực tuyến cho việc này hay cách đơn giản để làm điều này - làm cách nào tôi có thể chuyển đổi một mảng [String] thành mảng [Double]? Tôi có một tập tin CSV, khi đọc vào REPL được hiểu là giá trị chuỗi (mỗi dòng của tập tin có một kết hợp của các giá trị số nguyên và chuỗi) mà sẽ trả về một loại Array [String]. Tôi muốn mã hóa các giá trị chuỗi với giá trị double/int để trả về mảng [Double] để làm cho mảng đồng nhất. Có cách nào đơn giản để làm việc này không? Mọi hướng dẫn sẽ được đánh giá cao.Scala - chuyển đổi mảng [String] thành mảng [Double]

Những gì tôi đã làm cho đến bây giờ là:

def retrieveExamplesFromFile(fileName : String) : Array[Array[String]] = { 
    val items = for { 
    line <- Source.fromFile(fileName).getLines() 
    entries = line.split(",") 
    } yield entries 

    return items.toArray 
} 

Định dạng của mỗi dòng (trở lại như String []) là như vậy:

[[1.0, 2.0, item1], [5, 8.9, item2],....] 

Và để chuyển đổi mỗi dòng trong file CSV thành mảng kép, tôi chỉ có một định nghĩa psuedo được soạn thảo như vậy:

def generateNumbersForStringValues(values : Array[String]) : Array[Double] = { 
val line = for(item <- values) 
{ 
    //correct way? 
    item.replace("item1", "1.0") 
    item.replace("item2", "1.0")  
} 
return //unable to typecast/convert 
} 

Bất kỳ ý tưởng nào đều được chào đón. Cảm ơn bạn đã dành thời gian.

Trả lời

22

Bạn có thể muốn sử dụng map cùng với toDouble:

values.map(x => x.toDouble) 

Hoặc ngắn gọn hơn:

values.map(_.toDouble) 

Và đối với dự phòng cho các chuỗi phi đôi, bạn có thể xem xét sử dụng đơn vị Try (trong scala.util):

values.map(x => Try(x.toDouble).getOrElse(1.0)) 

Nếu bạn biết những gì mỗi dòng sẽ như thế nào, bạn cũng có thể làm khớp mẫu:

values map { 
    case Array(a, b, c) => Array(a.toDouble, b.toDouble, 1.0) 
} 
+0

Câu lệnh getOrElse hoặc đối sánh mẫu phù hợp nhất với tôi. Tuy nhiên, tôi muốn biết nếu tôi có thể thêm truy cập vào điều này thay vì quay trở lại chỉ 1.0 tất cả các thời gian? Tôi đã nghe nói về Range (n1, n2) nhưng đó không phải là những gì tôi đang tìm kiếm, tôi đang tìm kiếm một truy cập bởi vì tôi muốn item1 và item2 có số khác nhau (có thể liên tiếp). Điều này có thể không? –

+0

Chắc chắn - bạn có thể đặt bất kỳ logic nào bạn muốn trong mệnh đề 'getOrElse'. Ví dụ, bạn có thể tạo một biến lặp 'val fallbackIterator = Iterator.from (0)', và sau đó sử dụng 'getOrElse (fallbackIterator.next)', để mỗi cuộc gọi liên tiếp tới 'getOrElse' sẽ tăng giá trị dự phòng. –

+0

Tôi đã tìm kiếm rằng thử monad: không biết trong scala.util. v câu trả lời khá ở đây. – javadba

3

Bạn muốn chuyển đổi tất cả các chuỗi thành gấp đôi với dự phòng thành 1.0 cho tất cả các chuỗi không thể thay đổi? Đó sẽ là:

val x = Array(
    Array("1.0", "2.0", "item1"), 
    Array("5", "8.9", "item2")) 

x.map(_.map { y => 
    try { 
    y.toDouble 
    } catch { 
    case _: NumberFormatException => 1.0 
    } 
}) 
+1

tốt hơn để nắm bắt những 'java.lang.NumberFormatException' để tránh trình biên dịch cảnh báo – dhg

+0

@dhg và quan trọng hơn: để tránh bắt ngoại lệ gây tử vong như oom và các lỗi VM nội bộ. – rightfold

+0

@ райтфолд, có, nhưng đó là lý do tại sao trình biên dịch cảnh báo ... –

3

Mở rộng trên @ bình luận DaunnC, bạn có thể sử dụng tiện ích Try để làm điều này và phù hợp với mô hình trên kết quả vì vậy bạn có thể tránh được gọi get hoặc gói kết quả của bạn trong một Option:

import scala.util.{Try, Success, Failure} 

def main = { 
    val maybeDoubles = Array("5", "1.0", "8.5", "10.0", "item1", "item2") 

    val convertDoubles = maybeDoubles.map { x => 
    Try(x.toDouble) 
    } 

    val convertedArray = convertDoubles.map { 
    _ match { 
     case Success(res) => res 
     case Failure(f) => 1.0 
    } 
    } 

    convertedArray 
} 

này cho phép bạn mô hình phù hợp vào kết quả của Try, mà luôn luôn là một trong hai một Success hoặc Failure, mà không cần phải gọi số get hoặc kết quả khác.

Dưới đây là một số chi tiết thông tin về Thử kê biếu không của Mauricio Linhares: https://mauricio.github.io/2014/02/17/scala-either-try-and-the-m-word.html

+0

Sao chép/dán mã của bạn vào phương pháp chính của tôi và tôi nhận được O/P này: Thành công (5.0) Thành công (1.0) Thành công (8.5) Thành công (10.0) Thất bại (java.lang.NumberFormatException: Đối với chuỗi đầu vào: "item1") Thất bại (java.lang.NumberFormatException: Đối với chuỗi đầu vào: "item2") –

+0

Ah, đó có thể là do nó không tạo ra bản đồ cuối cùng. Tôi đã cập nhật câu trả lời của mình. –

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