2012-06-21 14 views
5

Tôi có một số List[Option[MyClass]] với None ở các vị trí ngẫu nhiên và tôi cần phải 'điền' lại danh sách đó, từ List[MyClass], duy trì thứ tự.Làm thế nào để thay thế (điền) Không có mục nào trong Danh sách Tùy chọn từ một Danh sách khác bằng cách sử dụng Scala thành ngữ?

Dưới đây là danh sách mẫu và kết quả mong đợi:

val listA = List(Some(3),None,Some(5),None,None) 
val listB = List(7,8,9) 
val expectedList = List(Some(3), Some(7), Some(5), Some(8), Some(9)) 

Vì vậy, làm thế nào sẽ là một thành ngữ Scala để xử lý danh sách đó?

Trả lời

13
def fillL[T](a:List[Option[T]], b:List[T]) = { 
    val iterB = b.iterator 
    a.map(_.orElse(Some(iterB.next))) 
} 
1

Giải pháp iterator được cho là thành ngữ Scala, và chắc chắn là ngắn gọn và dễ hiểu, nhưng nó không phải là chức năng thời gian -Bất kỳ bạn gọi next trên một iterator bạn vững trong đất tác dụng phụ.

Một cách tiếp cận chức năng hơn sẽ được sử dụng một lần:

def fillGaps[A](gappy: List[Option[A]], filler: List[A]) = 
    gappy.foldLeft((List.empty[Option[A]], filler)) { 
    case ((current, fs), Some(item)) => (current :+ Some(item), fs) 
    case ((current, f :: fs), None) => (current :+ Some(f), fs) 
    case ((current, Nil), None) => (current :+ None, Nil) 
    }._1 

Ở đây chúng ta di chuyển qua danh sách gappy khi vẫn duy trì hai danh sách khác: một cho các mặt hàng chúng tôi đã xử lý, và một cho phần còn lại yếu tố phụ.

Loại giải pháp này không nhất thiết phải tốt hơn giải pháp khác — Scala được thiết kế để cho phép bạn kết hợp các công trình chức năng và bắt buộc theo cách đó — nhưng nó có lợi thế tiềm năng.

+0

"bất kỳ lúc nào bạn gọi tiếp theo trên một trình lặp, bạn chắc chắn trong vùng đất của các tác dụng phụ." Đúng, nhưng trong trường hợp này, chúng được mã hóa gọn gàng trong phương thức, vẫn giữ nguyên trong suốt. –

+0

@Paul: Đúng vậy, tôi nghĩ giải pháp khác là tuyệt vời và đó là cách tiếp cận tôi muốn giải quyết vấn đề này trong mã của riêng tôi. Nhưng nó liên quan đến tác dụng phụ, và trong một số tình huống tương tự có thể không lý tưởng. –

0

Tôi chỉ muốn viết nó theo cách đơn giản, phù hợp về Thủ trưởng các danh sách và xử lý từng trường hợp một cách thích hợp:

def fill[A](l1: List[Option[A]], l2: List[A]) = (l1, l2) match { 
    case (Nil, _) => Nil 
    case (_, Nil) => l1 
    case (Some(x) :: xs, _) => Some(x) :: fill(xs, l2) 
    case (None :: xs, y :: ys) => Some(y) :: fill(xs, ys) 
} 

Có lẽ khi bạn chạy ra khỏi điều cần điền vào nó, bạn chỉ cần rời phần còn lại của None s trong đó.