2011-01-12 10 views
9

यह समस्या है जिसे मैंने हल किया है, हालांकि कुल अनिवार्य स्कैला नोब होने के नाते, मुझे लगता है कि मुझे कुछ पूरी तरह से सुरुचिपूर्ण नहीं मिला। सुधार के किसी भी विचार की सराहना की।स्कैला विशिष्ट स्थानों पर सूची में डालें

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) 

मैं सोच रहा था और अधिक सुरुचिपूर्ण समाधान कुछ इस तरह से प्राप्त हो सकता है, लेकिन यह है कि सिर्फ शुद्ध अटकलें है।

var final:List[Any] = (0 /: indexes) {(final, i) => final ::: ins ::: l1.slice(i, indexes(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) 

संपादित करें: स्पष्टीकरण जोड़ा।

हमारे यहाँ लक्ष्य है, एक और सूची (यहाँ xs --commonly सूचियों के लिए इस्तेमाल किया कहा जाता है में (extra कहा जाता है) चयनित तत्वों के सामने एक सूची डालने के लिए है के रूप में अगर एक बात है x तो उनमें से बहुत सारे बहुवचन xs होना चाहिए)। हम चाहते हैं कि यह किसी भी प्रकार की सूची में काम करे, इसलिए हम इसे सामान्य प्रकार [A] के साथ एनोटेट करते हैं।

कौन से तत्व सम्मिलन के लिए उम्मीदवार हैं? फ़ंक्शन लिखते समय, हम नहीं जानते हैं, इसलिए हम एक फ़ंक्शन प्रदान करते हैं जो प्रत्येक तत्व के लिए सत्य या गलत कहता है (p: A => Boolean)।

अब, x सूची में प्रत्येक तत्व के लिए, हम जांच करते हैं - क्या हमें सम्मिलन करना चाहिए (यानी p(x) सच है)? यदि हां, तो हम इसे अभी बनाते हैं: extra ::: List(x) केवल extra के तत्व हैं, इसके बाद एकल आइटम x है। (इसे extra :+ x के रूप में लिखना बेहतर हो सकता है - अंत में एक ही आइटम जोड़ें।) यदि नहीं, तो हमारे पास केवल एक ही आइटम है, लेकिन हम इसे केवल x के बजाय List(x) बनाते हैं क्योंकि हम सब कुछ एक ही प्रकार के लिए चाहते हैं। तो अब, अगर हम

4 1 2 3 4 

की तरह कुछ है और हमारे शर्त यह है कि हम 5 64 से पहले सम्मिलित है, हम

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

उत्पन्न यह ठीक है कि हम क्या चाहते हैं, को छोड़कर हम सूचियों की एक सूची है। आंतरिक सूचियों से छुटकारा पाने के लिए और एक ही सूची में सबकुछ फ़्लैटन करने के लिए, हम बस flatten पर कॉल करें।

+0

कला का कार्य;) पहला [ए] मतलब क्या है? क्या मतलब है? – Murgh

+0

पहला '[ए]' का अर्थ है कि यह एक सामान्य विधि है (यह कुछ प्रकार 'ए' पर काम करता है; बाद में' ए 'उसी संदर्भ का जिक्र कर रहा है)। '_' का अर्थ है" जो भी चर है "; यह 'x => x == 4' के लिए शॉर्टकट है। –

+2

'xs.map (..)। Flatten' को' xs.flatMap (..) 'के रूप में लिखा जा सकता है। – Landei

10

फ़्लैटन चाल प्यारा है, मैंने खुद को map का उपयोग करने का विचार नहीं किया होगा। मेरे परिप्रेक्ष्य से यह समस्या एक गुना के लिए एक सामान्य अनुप्रयोग है, क्योंकि आप सूची के माध्यम से जाना चाहते हैं और कुछ "एकत्रित करें" (परिणाम सूची)। हम अपने परिणाम सूची पीछे की ओर नहीं करना चाहते हैं, foldRight (यानी :\) यहाँ सही संस्करण है:

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

यहाँ एक और संभावना है, वास्तविक आवेषण को संभालने के लिए Seq#patch का उपयोग कर। आपको फ़ोल्ड राइट की आवश्यकता है ताकि बाद में सूचकांक पहले संभाले जा सकें (सम्मिलित करने के बाद सम्मिलित सभी तत्वों के सूचकांक को संशोधित करते हैं, इसलिए यह अन्यथा मुश्किल होगा)।

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) } 
} 
संबंधित मुद्दे