Scala xuống hoặc giảm vòng lặp for?


115

Trong Scala, bạn thường sử dụng một trình lặp để thực hiện một forvòng lặp theo thứ tự tăng dần như:

for(i <- 1 to 10){ code }

Bạn sẽ làm như thế nào để nó tăng từ 10 lên 1? Tôi đoán 10 to 1đưa ra một trình lặp trống (như toán học phạm vi thông thường)?

Tôi đã tạo một tập lệnh Scala giải quyết nó bằng cách gọi đảo ngược trên trình lặp, nhưng theo ý kiến ​​của tôi thì điều đó không tốt, có phải cách sau để thực hiện không?

def nBeers(n:Int) = n match {

    case 0 => ("No more bottles of beer on the wall, no more bottles of beer." +
               "\nGo to the store and buy some more, " +
               "99 bottles of beer on the wall.\n")

    case _ => (n + " bottles of beer on the wall, " + n +
               " bottles of beer.\n" +
               "Take one down and pass it around, " +
              (if((n-1)==0)
                   "no more"
               else
                   (n-1)) +
                   " bottles of beer on the wall.\n")
}

for(b <- (0 to 99).reverse)
    println(nBeers(b))

Câu trả lời:


229
scala> 10 to 1 by -1
res1: scala.collection.immutable.Range = Range(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

2
@Felix: Không có chi. Tôi cũng nên chỉ ra rằng untilbạn cũng có thể sử dụng nó tođể loại trừ điểm cuối bên phải khỏi phạm vi. Điểm cuối bên trái luôn được bao gồm.
Randall Schulz

Tôi đã biết về cho đến khi, cho đến cũng là một hàm trên Số nguyên, tuy nhiên, "by" phải là một hàm trên phạm vi / trình lặp bất kỳ thứ gì được trả về từ các hàm "đến" và "cho đến khi". Dù sao cũng cảm ơn :)
Felix

5
Câu trả lời của Randall là tốt nhất, nhưng tôi nghĩ Range.inclusive(10, 1, -1)xứng đáng được đề cập.
john sullivan

37

Câu trả lời từ @Randall là tốt như vàng, nhưng để hoàn thiện, tôi muốn thêm một vài biến thể:

scala> for (i <- (1 to 10).reverse) {code} //Will count in reverse.

scala> for (i <- 10 to(1,-1)) {code} //Same as with "by", just uglier.

9
1 cho lần đầu tiên một một, nhưng thứ hai là ác - ít có thể đọc hơn byvà IMO không nên được sử dụng trong mọi trường hợp
om-nôm-nom

4
Thứ hai là ác nhưng được xây dựng trực giác về những gì có sẵn
Zaheer

10

Scala cung cấp nhiều cách để làm việc theo hướng đi xuống trong vòng lặp.

Giải pháp thứ nhất: với "to" và "by"

//It will print 10 to 0. Here by -1 means it will decremented by -1.     
for(i <- 10 to 0 by -1){
    println(i)
}

Giải pháp thứ 2: Với "to" và "reverse"

for(i <- (0 to 10).reverse){
    println(i)
}

Giải pháp thứ 3: chỉ với "to"

//Here (0,-1) means the loop will execute till value 0 and decremented by -1.
for(i <- 10 to (0,-1)){
    println(i)
}

6

Được lập trình bằng Pascal, tôi thấy định nghĩa này rất hay khi sử dụng:

implicit class RichInt(val value: Int) extends AnyVal {
  def downto (n: Int) = value to n by -1
  def downtil (n: Int) = value until n by -1
}

Được sử dụng theo cách này:

for (i <- 10 downto 0) println(i)

Cảm ơn câu trả lời của bạn. Tôi đang gặp sự cố khi sử dụng giải pháp này. Đây là stacktrace của tôi:Error:(57, 17) value class may not be a member of another class implicit class RichInt(val value: Int) extends AnyVal { ^
robert

Như thông báo lỗi (không phải dấu vết ngăn xếp) gợi ý, bạn không thể xác định lớp giá trị bên trong của lớp khác. Hoặc xác định nó bên ngoài nó, oike trong một đối tượng hoặc loại bỏ extends AnyValmột phần (chỉ phục vụ để loại bỏ một số chi phí).
LP_

1

Bạn có thể sử dụng lớp Phạm vi:

val r1 = new Range(10, 0, -1)
for {
  i <- r1
} println(i)

1

Bạn có thể dùng : for (i <- 0 to 10 reverse) println(i)


0
for (i <- 10 to (0,-1))

Vòng lặp sẽ thực thi cho đến khi giá trị == 0, giảm mỗi lần -1.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.