2010-07-26 13 views
14

मेरी एक परियोजना में एक आम उपयोग केस आ रहा है। किसी बिंदु पर मुझे किसी तरह का संग्रह मिला है (सूची, सेक, इत्यादि ... कोई फर्क नहीं पड़ता) और इस संग्रह का एक तत्व। मैं क्या करना चाहता हूं कि दिए गए तत्व को इसके निम्नलिखित तत्व (यदि यह तत्व मौजूद है) या पिछले तत्व के साथ कुछ समय के साथ स्वैप करना है।स्कैला में संग्रह तत्वों को स्वैप करने का एक अच्छा और कार्यात्मक तरीका क्या है?

मैं प्रक्रियात्मक प्रोग्रामिंग तकनीकों का उपयोग करके इसे प्राप्त करने के तरीकों से अच्छी तरह से अवगत हूं। मेरा सवाल यह है कि कार्यात्मक प्रोग्रामिंग (स्कैला में) के माध्यम से समस्या को हल करने का एक अच्छा तरीका क्या होगा?


आपके उत्तरों के लिए धन्यवाद। मैंने स्वीकार किया कि मैंने खुद को सबसे ज्यादा समझ लिया है। चूंकि मैं एक कार्यात्मक प्रोग्रामर नहीं हूं (अभी तक) यह तय करना मेरे लिए मुश्किल है कि कौन सा जवाब वास्तव में सबसे अच्छा था। वे मेरी राय में बहुत अच्छे हैं।

+0

आप इस को देखा है? http://rosettacode.org/wiki/Generic_swap#Scala –

उत्तर

10

निम्नलिखित सूची में अगले तत्व के साथ स्वैप का कार्यात्मक संस्करण निम्नलिखित है, आप केवल तत्वों के साथ एक नई सूची बनाते हैं।

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

आपका उत्तर वही करता है जो मैंने इरादा किया था। मुझे पैटर्न मशीनिंग की याद दिलाने के लिए धन्यवाद। उच्च आदेश प्रकारों के लिए – aeisele

1

venechka की विधि के लिए एक वैकल्पिक कार्यान्वयन:

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

ध्यान दें कि यह एक त्रुटि के साथ विफल रहता है ई पिछले तत्व है।

आप दोनों तत्वों जानते हैं, और हर तत्व केवल एक बार होता है, यह और अधिक सुरुचिपूर्ण हो जाता है:

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

Landei के का एक जेनेरिक वर्जन:

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 
} 

कुछ उपयोगों:

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 :-) – Landei

8

जिपर एक शुद्ध कार्यात्मक डेटा संरचना है उस संरचना में एक सूचक। एक और तरीका रखो, यह कुछ संरचना में एक संदर्भ के साथ एक तत्व है।

उदाहरण के लिए, Scalaz लाइब्रेरी Zipper कक्षा प्रदान करती है जो फोकस में सूची के किसी विशेष तत्व के साथ एक सूची मॉडल करती है।

आप पहले तत्व पर केंद्रित एक सूची के लिए एक जिपर प्राप्त कर सकते हैं।

import scalaz._ 
import Scalaz._ 

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

आप, Zipper पर ज़िपर तरीकों का उपयोग कर का ध्यान केंद्रित स्थानांतरित कर सकते हैं, उदाहरण के लिए, आप अगले वर्तमान ध्यान केंद्रित करने से ऑफसेट करने के लिए स्थानांतरित कर सकते हैं।

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

इस तरह List.tail को छोड़कर यह याद आता है कि जहां यह किया गया है है।

फिर, एक बार जब आप अपना चुने हुए तत्व को ध्यान में रखते हैं, तो आप फोकस के आसपास के तत्वों को संशोधित कर सकते हैं।

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

नोट: इस नवीनतम Scalaz ट्रंक सिर, जिसमें जिपर की पूंछ पुनरावर्ती find और move तरीकों के साथ एक बग तय किया गया है के साथ है।

विधि आप चाहते हैं तो बस है:

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 

यह एक विधेय p के आधार पर एक तत्व से मेल खाता है। लेकिन आप आगे जा सकते हैं और सभी आस-पास के तत्वों पर भी विचार कर सकते हैं। उदाहरण के लिए, सम्मिलन प्रकार को लागू करने के लिए।

+0

जिपर का बहुत अच्छा स्पष्टीकरण। धन्यवाद। मैंने हमेशा सोचा कि इनके साथ क्या है। ;) – aeisele

+0

यह अच्छा होगा अगर आप पूरा फ़ंक्शन प्रदान कर सकें जो संग्रह, और तत्व लेता है, और संग्रह में उस तत्व की पहली घटना को अगले के साथ बदल देता है। –

0

कैसे के बारे में: dropIndex समारोह के लिए http://www.scala-lang.org/old/node/5286 को

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) 
    } 

प्रशंसा

संबंधित मुद्दे

 संबंधित मुद्दे