2011-10-08 19 views
7

Tôi là một newbie để scala, tôi chỉ viết một chức năng đơn giản để đảo ngược một chuỗi cho trước:Scala chuỗi ngược

def reverse(s: String) : String 
    for(i <- s.length - 1 to 0) yield s(i) 

sản lượng cung cấp cho trở lại một scala.collection.immutable.IndexedSeq [Char] và không thể chuyển đổi nó thành Chuỗi. (hoặc là một cái gì đó khác?)

làm cách nào để tôi viết chức năng này? chức năng

Trả lời

19

Lưu ý rằng có đã được xác định:

scala> val x = "scala is awesome" 
x: java.lang.String = scala is awesome 

scala> x.reverse 
res1: String = emosewa si alacs 

Nhưng nếu bạn muốn làm điều đó một mình:

def reverse(s: String) : String = 
(for(i <- s.length - 1 to 0 by -1) yield s(i)).mkString 

hoặc (đôi khi nó là tốt hơn để sử dụng until, nhưng có lẽ không trường hợp đó)

def reverse(s: String) : String = 
(for(i <- s.length until 0 by -1) yield s(i-1)).mkString 

Ngoài ra, lưu ý rằng nếu bạn sử dụng đếm ngược (từ lớn hơn o ne đến một giá trị nhỏ), bạn nên xác định bước tiêu cực hoặc bạn sẽ nhận được một tập rỗng:

scala> for(i <- x.length until 0) yield i 
res2: scala.collection.immutable.IndexedSeq[Int] = Vector() 

scala> for(i <- x.length until 0 by -1) yield i 
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) 
+0

cảm ơn om-nom-nom, tôi muốn tự mình thực hiện để tôi có thể tìm hiểu :) – Dzhu

7

Như đã nêu bởi om-nôm-nom, chú ý đến các by -1 (nếu bạn không thực sự lặp lại và kết quả của bạn sẽ trống). Bí quyết khác bạn có thể sử dụng là collection.breakOut.

Nó cũng có thể được cung cấp cho for hiểu như thế này:

def reverse(s: String): String = 
    (for(i <- s.length - 1 to 0 by -1) yield s(i))(collection.breakOut) 

reverse("foo") 
// String = oof 

Lợi ích của việc sử dụng breakOut là nó sẽ tránh tạo ra một cấu trúc trung gian như trong dung dịch mkString.

lưu ý: breakOut được tận dụng CanBuildFrom và các nhà xây dựng là một phần của nền tảng của thư viện bộ sưu tập được thiết kế lại giới thiệu trong scala 2.8.0

+0

Đẹp nhất! Không bao giờ nghĩ về 'breakOut' theo cách đó. –

8

Bạn cũng có thể viết này sử dụng một cách tiếp cận đệ quy (ném cái này chỉ trong vòng for fun)

def reverse(s: String): String = { 
    if (s.isEmpty) "" 
    else reverse(s.tail) + s.head 
} 
+1

Điều này sẽ không được tối ưu hóa – gurghet

10

Dưới đây là một phiên bản ngắn

def reverse(s: String) = ("" /: s)((a, x) => x + a) 

chỉnh sửa : hoặc thậm chí ngắn hơn, chúng ta có khó hiểu fantastically

def reverse(s: String) = ("" /: s)(_.+:(_)) 

nhưng tôi sẽ không thực sự khuyên này ...

+2

Xin chào Luigi, bạn có thể đưa ra một giải thích ngắn cho mã của bạn không?thanks – Dzhu

+1

Ước gì tôi đã nghĩ về điều này. @ Dzhu nó chỉ sử dụng một 'foldLeft' (' /: 'chỉ là một tên viết tắt của phương thức đó), lấy giá trị ban đầu và sau đó áp dụng toán tử cho mỗi giá trị của một chuỗi từ trái sang phải. Trong trường hợp này, chuỗi là chuỗi và toán tử chỉ cần thêm các ký tự của chuỗi vào kết quả. –

+0

@Dzhu '" "/: s' là một cuộc gọi phương thức trong ký hiệu infix. Cuộc gọi là trên 's' với đối số' "" 'vì phương thức' /: 'kết thúc bằng': '. Nếu bạn tra cứu String trong các tài liệu Scala, bạn sẽ không tìm thấy nó vì nó chỉ là lớp Java, nhưng bạn sẽ tìm thấy 'StringOps' mà Strings được chuyển đổi hoàn toàn, và ở đây bạn sẽ tìm thấy phương thức' /: '. Nó được curried và lấy một đối số thứ hai, đó là (ở đây) một hàm ẩn danh của kiểu '(String, Char) => String'. Xem thêm http://stackoverflow.com/q/7339618/770361, http://stackoverflow.com/questions/2293592/functional-programming-scala-map-and-fold-left/2303291#2303291 –

3

Tất cả các câu trả lời trên là đúng và đây là mất của tôi :

scala> val reverseString = (str: String) => str.foldLeft("")((accumulator, nextChar) => nextChar + accumulator) 
reverseString: String => java.lang.String = <function1> 

scala> reverseString.apply("qwerty") 
res0: java.lang.String = ytrewq 
Các vấn đề liên quan