2013-05-12 19 views
5

Sử dụng một Vector [Vector [Int]] tham khảo v, và biểu thức để tìm một số num đưa ra:Làm thế nào để nắm bắt được giá trị khớp trong bên trong biểu thức vector indexWhere?

val posX = v.indexWhere(_.indexOf(num) > -1) 

Có cách nào để nắm bắt được giá trị của _.indexOf (num) để sử dụng sau biểu thức (tức là giá trị posY)? Các dấu hiệu sau đây báo lỗi 'Bắt ​​đầu bất hợp pháp cụm từ đơn giản':

val posX = v.indexWhere((val posY = _.indexOf(num)) > -1) 
+2

Xin chào từ khóa học Lập trình chức năng ở Scala! :) –

Trả lời

5

Có rất nhiều cách chức năng tốt để thực hiện việc này. Sau đây có thể là một trong những điều ngắn gọn hơn:

val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6), Vector(7, 8, 9)) 
val num = 4 

val Some((posY, posX)) = v.map(_ indexOf num).zipWithIndex.find(_._1 > -1) 
// posY: Int = 0 
// posX: Int = 1 

Lưu ý rằng có rất nhiều bộ sưu tập trung gian, một phần mà chúng tôi không cần, vv Nếu bạn đang gọi điều này rất nhiều hoặc trên các bộ sưu tập rất lớn, bạn không may có thể cần phải thực hiện một cách tiếp cận cấp bách hơn. Trong trường hợp đó, tôi khuyên bạn nên đóng gói tất cả những điều khó chịu:

def locationOf(v: Vector[Vector[Int]])(num: Int): Option[(Int, Int)] = { 
    var i, j = 0 
    var found = false 

    while (i < v.size && !found) { 
    j = 0 

    while (j < v(i).size && !found) 
     if (v(i)(j) == num) found = true else j += 1 

    if (!found) i += 1 
    } 

    if (!found) None else Some(i, j) 
} 

Không thanh lịch, nhưng phương pháp này có thể sẽ nhanh hơn và hiệu quả hơn. Nó đủ nhỏ đến nỗi nó không có khả năng chứa bất kỳ lỗi nào mà loại lập trình này dễ bị, và nó liên quan đến sự minh bạch - tất cả các đột biến là cục bộ.

2

Từ chiếc ghế bành của tôi,

scala> val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6), Vector(7, 8, 9)) 

scala> v.zipWithIndex collectFirst { 
    | case (e, i) if (e indexOf num) >= 0 => 
    | (i, e indexOf num) 
    | } 
res7: Option[(Int, Int)] = Some((1,0)) 

Tôi đã không làm toán ghế bành, nhưng đó là một bộ sưu tập trung so với Travis. Nhưng xem nhận xét của Travis rằng kết quả chỉ mục bên trong được tính hai lần ở đây, và toàn bộ vấn đề không phải là để làm điều đó.

+1

Bạn có thể thêm '.view' trước' .zipWithIndex' để lấy 0 bộ sưu tập trung gian. – senia

+2

Lưu ý rằng điều này tiết kiệm một bộ sưu tập trung gian bằng cách tìm kiếm mỗi vector bên trong hai lần ('e indexOf num'). –

5

Nếu chúng ta không quan tâm sử dụng một biến thì chúng ta có thể chụp indexOf() giá trị của Vector trong (_ trong các mã dưới đây) trong một var và sử dụng nó sau này để xây dựng vị trí y:

val posX = v.indexWhere(_.indexOf(num) > -1) 
val posY = v(posX).indexOf(num) 
0

Đây là một giải pháp sẽ chỉ đánh giá cho đến khi tìm thấy phần tử được yêu cầu. Cá nhân tôi tìm thấy nó dễ đọc hơn và bạn có thể tái sử dụng nó trên các chương trình. Bạn rõ ràng có thể làm cho điều này tổng quát hơn nếu cần thiết.

val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6)) 

def findElem(i: Int, vs: Vector[Vector[Int]]): (Int, Int) = 
    (for { 
     row <- vs.indices.toStream 
     col <- vs(row).indices.toStream 
     if vs(row)(col) == i 
    } yield (row, col)).head 

findElem(5, v) // (1, 1) 

Bạn có thể xóa phương thức .toStream nếu bạn muốn tất cả các vị trí. Sử dụng .toStream chỉ có nghĩa là bạn sẽ chỉ đánh giá cho đến lần xuất hiện đầu tiên.

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