2012-06-23 26 views
27

Vì vậy, tôi đang làm việc thông qua một vài trong số các bài tập trong "Scala cho Nóng lòng chờ đợi" và một trong số họ là:Char hoặc String -> Giá trị Unicode trong Scala?

Viết một vòng lặp for để tính toán là sản phẩm của các mã Unicode của tất cả các ký tự trong một chuỗi. Ví dụ: sản phẩm của các ký tự trong "Hello" là 9415087488 L.

Vấn đề tiếp theo là làm tương tự, nhưng không có vòng lặp for - nó gợi ý rằng chúng ta nên kiểm tra StringOps trong Scaladoc.

Tôi đã kiểm tra phần RichCharStringOps trong Scaladoc và có lẽ tôi đang hiểu sai hoặc tìm kiếm địa điểm sai, nhưng tôi không thể tìm thấy bất kỳ điều gì khiến tôi khớp với kết quả của chúng. Tôi đã cố gắng rất nhiều:

scala> x.foldLeft(1)(_ * _.toInt) 
res0: Int = 825152896 

scala> x.foldLeft(1)(_ * _.getNumericValue) 
res5: Int = 2518992 

scala> x.foldLeft(1)(_ * _.intValue()) 
res6: Int = 825152896 

scala> var x = 1 
x: Int = 1 

scala> for (c <- "Hello") x *= c.toInt 

scala> x 
res12: Int = 825152896 

Không phù hợp với đầu ra của chúng.

Làm cách nào để thực hiện việc này, trong cả hai cách for và không phải for?

Cảm ơn!

+0

Có một cách khác, nếu bạn làm điều đó trong hai bước. Gợi ý: cuối cùng của hai phương thức chỉ có một tham số ngầm định. –

Trả lời

26

Khi bạn làm x.foldLeft(1)(_ * _.toInt), loại kết quả sẽ được suy luận đến một số Int, nhưng 9415087488 quá lớn cho một số Int để lưu trữ.

Vì vậy, bạn cần phải thông báo cho Scala sử dụng Long để lưu trữ.

scala> val x = "Hello" 
x: java.lang.String = Hello 

scala> x.foldLeft(1L)(_ * _.toInt) 
res1: Long = 9415087488 

scala> var x: Long = 1 
x: Long = 1 

scala> for (c <- "Hello") x *= c.toInt 

scala> x 
res7: Long = 9415087488 
+0

Ahhh hiểu rồi. Cảm ơn! – adelbertc

+5

Cảm ơn tôi. Thật kỳ lạ, trong phiên bản pdf tôi vừa tải xuống, giá trị sai được đưa ra (825152896). – Markus

+0

lạ, nhưng với "for (fi <-" Hello ") i * = fi.toChar" Tôi có cùng giá trị như trong sách. Hừm. –

12

Nếu bạn chuyển đổi mỗi RichChar của chuỗi .toLong nó cũng hoạt động. Ví dụ, điều này:

str.map (_.toLong).product - công việc của mỹ và không foldLeft hoặc chu kỳ

Đây là cyclic biến thể:

def product(str: String): Long = { 
    var prod: Long = 1 
    for (ch <- str) prod *= ch 
    prod 
} 
3

Cách đơn giản nhất mà tôi đã tìm thấy để làm điều này là:

"Hello".foldLeft(1L)((x:Long, y:Char) => x*y) 

Phương thức này lấy hai tham số: một hàm Long và một hàm đại diện có một giá trị Long và một Char và trả về giá trị Long. Bạn có thể vượt qua một chức năng ẩn danh trực tiếp như thế này, hoặc bạn có thể xác định các chức năng khác và vượt qua nó trong, như vậy:

def multiply(x:Long, y:Char) = { 
    x*y 
} 
"Hello".foldLeft(1L)(multiply) 
4

Dưới đây là một cách khác:

scala> (for (c <- "Hello") yield c.toLong).product 
res36: Long = 9415087488 
6

Có một "sản phẩm" đặc biệt trong StringOps nhân lên các phần tử của bộ sưu tập. Nhưng nó sử dụng loại Char bởi vì chuỗi bao gồm các phần tử char. Và chúng tôi đang có tràn trong khi cố gắng tính toán "Hello" .product. Vì vậy, tôi chuyển đổi chuỗi để Vector của các giá trị dài Unicode bằng "Hello" .map (_ tolong.) Và tính toán các sản phẩm của các yếu tố của mình bằng mã này:

scala> "Hello".map(_.toLong).product 
res79: Long = 9415087488 
+0

Cảm ơn! Tôi nghi ngờ một tràn, quá. Nhưng đã không chắc chắn làm thế nào để yêu cầu nó để bản đồ nó đến một Long. – asgs

+0

Vòng lặp for trong câu trả lời của Rihad và bản đồ trong câu trả lời này là các biến thể không hợp lý. Trình biên dịch chuyển đổi vòng lặp for thành bản đồ, tôi tin. Đó là một vấn đề của hương vị mà bạn sử dụng. – airfoyle

2

Tôi nghĩ rằng việc chuyển đổi bản đồ trung gian là không hiệu quả bởi vì trong trường hợp này bộ sưu tập được lặp lại hai lần: một lần để tạo bản đồ của thời gian dài và lần thứ hai để nhân tất cả các phần tử. Bộ sưu tập tạm thời không cần thiết của Long cũng không cần thiết.Tôi cung cấp cho lá phiếu của tôi để

"Hello".foldLeft(1L)(_ * _) 
0

Một biến thể: "Hello".aggregate(1L)({(prod,ch) => prod * ch.toLong}, {(p1,p2)=>p1*p2})

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