2010-07-26 24 views
14

Trong một dự án của tôi, một trường hợp sử dụng phổ biến vẫn tiếp tục xuất hiện. Tại một số điểm tôi đã có một bộ sưu tập được sắp xếp của một số loại (Danh sách, Seq, vv ... không quan trọng) và một phần của bộ sưu tập này. Những gì tôi muốn làm là để trao đổi các yếu tố nhất định với nó sau yếu tố (nếu yếu tố này tồn tại) hoặc tại một số lần với các yếu tố trước.Cách tốt nhất và chức năng để trao đổi các yếu tố thu thập trong Scala là gì?

Tôi biết rõ các cách để đạt được điều này bằng cách sử dụng các kỹ thuật lập trình thủ tục. Câu hỏi của tôi là những gì sẽ là một cách tốt để giải quyết vấn đề bằng phương tiện lập trình chức năng (trong Scala)?


Cảm ơn tất cả các câu trả lời của bạn. Tôi chấp nhận cái mà bản thân tôi đã hiểu nhất. Vì tôi không phải là một lập trình viên chức năng (chưa), thật khó để tôi quyết định câu trả lời nào thực sự là tốt nhất. Tất cả họ đều khá tốt trong quan điểm của tôi.

+0

Bạn đã nhìn này? http://rosettacode.org/wiki/Generic_swap#Scala –

Trả lời

10

Sau đây là phiên bản hoán đổi chức năng với phần tử tiếp theo trong danh sách, bạn chỉ cần tạo danh sách mới với các phần tử được hoán đổi.

def swapWithNext[T](l: List[T], e : T) : List[T] = l match { 
    case Nil => Nil 
    case `e`::next::tl => next::e::tl 
    case hd::tl => hd::swapWithNext(tl, e) 
} 
+0

câu trả lời của bạn thực hiện chính xác những gì tôi dự định. cảm ơn bạn đã nhắc tôi về mô hình machting. – aeisele

1

An thực hiện thay thế cho phương pháp venechka của:

def swapWithNext[T](l: List[T], e: T): List[T] = { 
    val (h,t) = l.span(_ != e) 
    h ::: t.tail.head :: e :: t.tail.tail 
} 

Lưu ý rằng điều này không thành công với một lỗi nếu e là yếu tố cuối cùng.

Nếu bạn biết cả hai yếu tố, và mọi phần tử chỉ xảy ra một lần, nó được thêm thanh lịch:

def swap[T](l: List[T], a:T, b:T) : List[T] = l.map(_ match { 
    case `a` => b 
    case `b` => a 
    case e => e } 
) 
5

Một phiên bản generic của Landei của:

import scala.collection.generic.CanBuildFrom 
import scala.collection.SeqLike 
def swapWithNext[A,CC](cc: CC, e: A)(implicit w1: CC => SeqLike[A,CC], 
             w2: CanBuildFrom[CC,A,CC]): CC = { 
    val seq: SeqLike[A,CC] = cc 
    val (h,t) = seq.span(_ != e) 
    val (m,l) = (t.head,t.tail) 
    if(l.isEmpty) cc 
    else (h :+ l.head :+ m) ++ l.tail 
} 

một số tập quán:

scala> swapWithNext(List(1,2,3,4),3) 
res0: List[Int] = List(1, 2, 4, 3) 

scala> swapWithNext("abcdef",'d') 
res2: java.lang.String = abcedf 

scala> swapWithNext(Array(1,2,3,4,5),2) 
res3: Array[Int] = Array(1, 3, 2, 4, 5) 

scala> swapWithNext(Seq(1,2,3,4),3) 
res4: Seq[Int] = List(1, 2, 4, 3) 

scala> 
+0

+1 cho các loại lệnh cao hơn :-) – Landei

8

A zipper là cấu trúc dữ liệu chức năng thuần túy w ith một con trỏ vào cấu trúc đó. Nói cách khác, nó là một yếu tố với một bối cảnh trong một số cấu trúc.

Ví dụ: thư viện Scalaz cung cấp lớp học Zipper mô hình danh sách có phần tử cụ thể trong danh sách được lấy nét.

Bạn có thể lấy dây kéo cho danh sách, tập trung vào phần tử đầu tiên.

import scalaz._ 
import Scalaz._ 

val z: Option[Zipper[Int]] = List(1,2,3,4).toZipper 

Bạn có thể chuyển trọng tâm của khóa kéo sử dụng phương pháp trên Zipper, ví dụ, bạn có thể di chuyển đến tiếp theo bù đắp từ các trọng tâm hiện nay.

val z2: Option[Zipper[Int]] = z >>= (_.next) 

Điều này giống như List.tail ngoại trừ việc nó nhớ vị trí của nó.

Sau đó, khi bạn đã chọn phần tử đã chọn, bạn có thể sửa đổi các phần tử xung quanh tiêu điểm.

val swappedWithNext: Option[Zipper[Int]] = 
    for (x <- z2; 
     y <- x.delete) 
    yield y.insertLeft(x.focus) 

Lưu ý: đây là với người đứng đầu Scalaz thân mới nhất, trong đó có một lỗi với đuôi-đệ quy findmove phương pháp Zipper đã được cố định.

Phương pháp bạn muốn là sau đó chỉ cần:

def swapWithNext[T](l: List[T], p: T => Boolean) : List[T] = (for { 
    z <- l.toZipper 
    y <- z.findZ(p) 
    x <- y.delete 
} yield x.insertLeft(y.focus).toStream.toList) getOrElse l 

này phù hợp với một yếu tố dựa trên một vị p. Nhưng bạn có thể đi xa hơn và xem xét tất cả các yếu tố lân cận. Ví dụ, để thực hiện một sắp xếp chèn.

+0

Giải thích rất tốt về Dây kéo. Cảm ơn bạn. Tôi luôn tự hỏi điều gì với những thứ này. ;) – aeisele

+0

Sẽ rất tuyệt nếu bạn có thể cung cấp đầy đủ chức năng lấy một bộ sưu tập và phần tử, và hoán đổi lần xuất hiện đầu tiên của phần tử đó trong bộ sưu tập với phần tử tiếp theo. –

0

Làm thế nào về:

val identifierPosition = 3; 
    val l = "this is a identifierhere here"; 
    val sl = l.split(" ").toList; 

    val elementAtPos = sl(identifierPosition) 
    val swapped = elementAtPos :: dropIndex(sl , identifierPosition) 

    println(swapped) 

    def dropIndex[T](xs: List[T], n: Int) : List[T] = { 
    val (l1, l2) = xs splitAt n 
    l1 ::: (l2 drop 1) 
    } 

thanh danh cho http://www.scala-lang.org/old/node/5286 cho chức năng dropIndex

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