2011-01-12 19 views
9

Đây là vấn đề mà tôi đã giải quyết, tuy nhiên là một Scala noob cấp bách, tôi cảm thấy tôi đã tìm thấy một thứ hoàn toàn không thanh lịch. Bất kỳ ý tưởng cải tiến nào được đánh giá cao.Scala chèn vào danh sách tại các địa điểm cụ thể

val l1 = 4 :: 1 :: 2 :: 3 :: 4 :: Nil // original list 
val insert = List(88,99) // list I want to insert on certain places 

// method that finds all indexes of a particular element in a particular list 
def indexesOf(element:Any, inList:List[Any]) = { 
     var indexes = List[Int]() 
     for(i <- 0 until inList.length) { 
       if(inList(i) == element) indexes = indexes :+ i 
     } 
     indexes 
} 


var indexes = indexesOf(4, l1) // get indexes where 4 appears in the original list 

println(indexes) 

var result = List[Any]() 

// iterate through indexes and insert in front 
for(i <- 0 until indexes.length) { 
     var prev = if(i == 0) 0 else indexes(i-1) 
     result = result ::: l1.slice(prev, indexes(i)) ::: insert 
} 
result = result ::: l1.drop(indexes.last) // append the last bit from original list 

println(result) 

Tôi đã nghĩ rằng giải pháp thanh lịch hơn sẽ đạt được với một cái gì đó như thế này, nhưng đó chỉ là suy đoán thuần túy.

var final:List[Any] = (0 /: indexes) {(final, i) => final ::: ins ::: l1.slice(i, indexes(i)) 

Trả lời

14
def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = { 
    xs.map(x => if (p(x)) extra ::: List(x) else List(x)).flatten 
} 

scala> insert(List(4,1,2,3,4),List(88,99)){_ == 4} 
res3: List[Int] = List(88, 99, 4, 1, 2, 3, 88, 99, 4) 

Edit: giải thích thêm.

mục tiêu của chúng tôi ở đây là để chèn một danh sách (gọi tắt là extra) ở phía trước của các yếu tố được lựa chọn trong danh sách khác (ở đây gọi là xs --commonly sử dụng cho các danh sách, như thể có một điều x sau đó rất nhiều trong số họ phải là số nhiều xs). Chúng tôi muốn điều này hoạt động trên bất kỳ loại danh sách nào mà chúng tôi có thể có, vì vậy chúng tôi chú thích nó với loại chung [A].

Yếu tố nào là ứng cử viên để chèn? Khi viết hàm, chúng ta không biết, vì vậy chúng tôi cung cấp một hàm cho biết đúng hoặc sai cho mỗi phần tử (p: A => Boolean).

Hiện tại, đối với mỗi thành phần trong danh sách x, chúng tôi kiểm tra - chúng tôi có nên thực hiện việc chèn (tức là p(x) đúng) không? Nếu có, chúng tôi chỉ xây dựng nó: extra ::: List(x) chỉ là các phần tử của extra theo sau là một mục duy nhất x. (Có thể viết tốt hơn là extra :+ x - thêm một mục vào cuối.) Nếu không, chúng tôi chỉ có một mục duy nhất, nhưng chúng tôi làm cho nó List(x) thay vì chỉ x vì chúng tôi muốn mọi thứ có cùng loại. Vì vậy, bây giờ, nếu chúng ta có một cái gì đó giống như

4 1 2 3 4 

và điều kiện của chúng tôi là chúng ta chèn 5 6 trước 4, chúng tôi tạo ra

List(5 6 4) List(1) List(2) List(3) List(5 6 4) 

Đây chính là điều chúng tôi muốn, ngoại trừ chúng ta có một danh sách liệt kê. Để loại bỏ các danh sách bên trong và làm phẳng mọi thứ vào một danh sách, chúng tôi chỉ gọi flatten.

+0

Tác phẩm nghệ thuật;) Ý nghĩa đầu tiên [A] là gì? Nghĩa là gì? – Murgh

+0

Đầu tiên '[A]' có nghĩa rằng nó là một phương thức chung (nó hoạt động trên một số loại 'A'; sau này' A 'đang đề cập đến cùng một). '_' có nghĩa là" bất kỳ biến nào là "; đó là một phím tắt cho 'x => x == 4'. –

+2

'xs.map (..). Flatten' có thể được viết dưới dạng' xs.flatMap (..) '. – Landei

10

Thủ thuật làm phẳng thật dễ thương, tôi sẽ không tự mình nghĩ đến việc sử dụng map ở đây. Theo quan điểm của tôi, vấn đề này là một ứng dụng điển hình cho một nếp gấp, khi bạn muốn đi qua danh sách và "thu thập" một cái gì đó (danh sách kết quả). Như chúng ta đã không muốn danh sách kết quả của chúng tôi về phía sau, foldRight (còn gọi là :\) là ở đây phiên bản đúng:

def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = 
    xs.foldRight(List[A]())((x,xs) => if (p(x)) extra ::: (x :: xs) else x :: xs) 
3

Dưới đây là một khả năng khác, sử dụng Seq#patch để xử lý chèn thực tế. Bạn cần phải foldRight để các chỉ mục sau đó được xử lý đầu tiên (chèn thay đổi các chỉ số của tất cả các phần tử sau khi chèn, do đó, nó sẽ là khôn lanh nếu không).

def insert[A](xs: Seq[A], ys: Seq[A])(pred: A => Boolean) = { 
    val positions = xs.zipWithIndex filter(x => pred(x._1)) map(_._2) 
    positions.foldRight(xs) { (pos, xs) => xs patch (pos, ys, 0) } 
} 
Các vấn đề liên quan