Việc sử dụng withFilter thay vì filter có luôn hiệu quả hơn khi sau đó áp dụng các chức năng như bản đồ, bản đồ phẳng, v.v. không?
Tại sao chỉ hỗ trợ map, flatmap và foreach? (Các chức năng mong đợi như forall / cũng tồn tại)
Việc sử dụng withFilter thay vì filter có luôn hiệu quả hơn khi sau đó áp dụng các chức năng như bản đồ, bản đồ phẳng, v.v. không?
Tại sao chỉ hỗ trợ map, flatmap và foreach? (Các chức năng mong đợi như forall / cũng tồn tại)
Câu trả lời:
Từ tài liệu Scala :
Lưu ý: sự khác biệt giữa
c filter p
vàc withFilter p
là cựu tạo ra một bộ sưu tập mới, trong khi sau này chỉ hạn chế lĩnh vực tiếp theomap
,flatMap
,foreach
, vàwithFilter
các hoạt động.
Vì vậy, filter
sẽ lấy bộ sưu tập ban đầu và tạo ra một bộ sưu tập mới, nhưng withFilter
sẽ không nghiêm ngặt (tức là lười biếng) chuyển các giá trị chưa được lọc qua các cuộc gọi / map
/ sau đó , lưu một lần thứ hai qua bộ sưu tập (đã lọc). Do đó, nó sẽ hiệu quả hơn khi chuyển qua các cuộc gọi phương thức tiếp theo này.flatMap
withFilter
Trên thực tế, withFilter
nó được thiết kế đặc biệt để làm việc với chuỗi các phương pháp này, đó là những gì mà một để hiểu được loại bỏ thành. Không có phương thức nào khác (chẳng hạn như forall
/ exists
) được yêu cầu cho việc này, vì vậy chúng đã không được thêm vào FilterMonadic
kiểu trả về withFilter
.
view
nếu bạn muốn bản đồ / bộ lọc lười biếng.
view
và withFilter
? Tại sao chế độ xem không được sử dụng for-loops
?
Don’t create temporary collections
trong phần được liên kết.
withFilter
, bản thân Martin Odersky cũng sử dụng nó một cách rõ ràng trong các khóa học Scala của anh ấy trên Coursera, điều mà tôi thực sự khuyên bạn nên sử dụng. Cho rằng anh ta làm như vậy, điều đó có thể mang lại cho người khác cảm giác thoải mái khi làm như vậy, mặc dù sự khác biệt thường chỉ là 1 ký tự. Ví dụ seq.view filter p
vs seq withFilter p
.
Ngoài câu trả lời xuất sắc của Shadowlands , tôi muốn đưa ra một ví dụ trực quan về sự khác biệt giữa filter
và withFilter
.
Hãy xem xét đoạn mã sau
val list = List(1, 2, 3)
var go = true
val result = for(i <- list; if(go)) yield {
go = false
i
}
Hầu hết mọi người mong đợi result
được bằng List(1)
. Đây là trường hợp kể từ Scala 2.8, vì tính dễ hiểu được dịch sang
val result = list withFilter {
case i => go
} map {
case i => {
go = false
i
}
}
Như bạn có thể thấy, bản dịch chuyển đổi điều kiện thành lời gọi tới withFilter
. Trước Scala 2.8, tính dễ hiểu đã được dịch thành những thứ như sau:
val r2 = list filter {
case i => go
} map {
case i => {
go = false
i
}
}
Sử dụng filter
, giá trị của result
sẽ là khá khác nhau: List(1, 2, 3)
. Thực tế là chúng tôi đang tạo go
cờ false
không ảnh hưởng đến bộ lọc, vì bộ lọc đã được thực hiện. Một lần nữa, trong Scala 2.8, vấn đề này được giải quyết bằng cách sử dụng withFilter
. Khi withFilter
được sử dụng, điều kiện được đánh giá mỗi khi một phần tử được truy cập bên trong một map
phương thức.
Tham khảo : - p.120, Scala in action (bao gồm Scala 2.10), Manning Publications, Milanjan Raychaudhuri - Suy nghĩ của Odersky về bản dịch dễ hiểu
Lý do chính bởi vì forall / being không được triển khai là trường hợp sử dụng là:
Để triển khai forall / being, chúng ta cần lấy tất cả các phần tử, loại bỏ sự lười biếng.
Ví dụ:
import scala.collection.AbstractIterator
class RandomIntIterator extends AbstractIterator[Int] {
val rand = new java.util.Random
def next: Int = rand.nextInt()
def hasNext: Boolean = true
}
//rand_integers is an infinite random integers iterator
val rand_integers = new RandomIntIterator
val rand_naturals =
rand_integers.withFilter(_ > 0)
val rand_even_naturals =
rand_naturals.withFilter(_ % 2 == 0)
println(rand_even_naturals.map(identity).take(10).toList)
//calling a second time we get
//another ten-tuple of random even naturals
println(rand_even_naturals.map(identity).take(10).toList)
Lưu ý rằng ten_rand_even_naturals vẫn là một trình lặp. Chỉ khi chúng tôi gọi toList , các số ngẫu nhiên sẽ được tạo và lọc theo chuỗi
Lưu ý rằng bản đồ (danh tính) tương đương với bản đồ (i => i) và nó được sử dụng ở đây để chuyển đổi đối tượng withFilter trở lại kiểu ban đầu (ví dụ: một bộ sưu tập, một luồng, một trình lặp)
Sử dụng để tạo ra lợi nhuận có thể là một công việc xung quanh, ví dụ:
for {
e <- col;
if e isNotEmpty
} yield e.get(0)
Như một giải pháp thay thế, bạn có thể triển khai các chức năng khác chỉ với map
và flatMap
.
Hơn nữa, tối ưu hóa này vô dụng trên các bộ sưu tập nhỏ…