एक अपरिवर्तनीय सूची से एक तत्व को "हटाने" के लिए एक मुहावरेदार स्काला तरीका क्या है?


84

मेरे पास एक सूची है, जिसमें ऐसे तत्व हो सकते हैं जो समान के रूप में तुलना करेंगे। मैं एक समान सूची चाहूंगा, लेकिन एक तत्व को हटा दिया जाएगा। तो (ए, बी, सी, बी, डी) से मैं ए (ए, सी, बी, डी) प्राप्त करने के लिए सिर्फ एक बी को "हटाने" में सक्षम होना चाहूंगा। परिणाम में तत्वों का क्रम मायने नहीं रखता है।

मेरे पास वर्किंग कोड है, जो स्काला में एक लिस्प-प्रेरित तरीके से लिखा गया है। क्या ऐसा करने का एक अधिक मुहावरेदार तरीका है?

प्रसंग एक कार्ड गेम है जहाँ मानक कार्ड के दो डेक खेलने में होते हैं, इसलिए डुप्लिकेट कार्ड हो सकते हैं लेकिन फिर भी एक समय में एक ही खेला जाता है।

def removeOne(c: Card, left: List[Card], right: List[Card]): List[Card] = {
  if (Nil == right) {
    return left
  }
  if (c == right.head) {
    return left ::: right.tail
  }
  return removeOne(c, right.head :: left, right.tail)
}

def removeCard(c: Card, cards: List[Card]): List[Card] = {
  return removeOne(c, Nil, cards)
}

एक नोट जोड़ा कि इस विशिष्ट मामले में परिणाम सूची का क्रम मायने नहीं रखता है।
गाविलन कोमुन

तो List[Card]इस सवाल में एक खिलाड़ी का हाथ है?
केन ब्लूम

@ केन, हाँ यह सही है कि एक खिलाड़ी का हाथ है।
गाविलन कोमुन

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

क्लोजर के लिए यह सवाल: stackoverflow.com/questions/7662447/…
गाविलन कोमुन

जवाबों:


144

मैंने इस संभावना को ऊपर के उत्तर में नहीं देखा है, इसलिए:

scala> def remove(num: Int, list: List[Int]) = list diff List(num)
remove: (num: Int,list: List[Int])List[Int]

scala> remove(2,List(1,2,3,4,5))
res2: List[Int] = List(1, 3, 4, 5)

संपादित करें:

scala> remove(2,List(2,2,2))
res0: List[Int] = List(2, 2)

जादू की तरह :-)।


18
अच्छा! मैं सूची में एक और 2 जोड़ूंगा ताकि यह स्पष्ट हो सके कि केवल एक तत्व हटा दिया गया है।
फ्रैंक एस। थॉमस

39

आप filterNotविधि का उपयोग कर सकते हैं ।

val data = "test"
list = List("this", "is", "a", "test")
list.filterNot(elm => elm == data)

21
यह उन सभी तत्वों को हटा देगा जो "परीक्षण" के बराबर हैं - जो नहीं पूछा गया है;)
y allsʞǝla

1
वास्तव में यह वही करेगा जो आपको चाहिए। यह सूची से उन सभी तत्वों को लौटा देगा, जो "परीक्षण" के बराबर नहीं हैं। ध्यान दें कि यह फ़िल्टर
btbvoy

14
मूल प्रश्न यह था कि एक SINGLE उदाहरण कैसे हटाया जाए। सभी उदाहरण नहीं।
ty1824

@ सोरेन माथियासेन अगर मैं वैल डेटा = सीक्व ("टेस्ट", "ए") जैसे अनुक्रम के कई तत्वों को फ़िल्टर करना चाहता हूं, तो यह कैसे करना है?
BdEngineer

18

आप यह कोशिश कर सकते हैं:

scala> val (left,right) = List(1,2,3,2,4).span(_ != 2)
left: List[Int] = List(1)
right: List[Int] = List(2, 3, 2, 4)

scala> left ::: right.tail                            
res7: List[Int] = List(1, 3, 2, 4)

और विधि के रूप में:

def removeInt(i: Int, li: List[Int]) = {
   val (left, right) = li.span(_ != i)
   left ::: right.drop(1)
}

3
यह ध्यान देने योग्य है कि left ::: right.drop(1)यदि कथन के साथ कम है isEmpty
रेक्स केर

2
धन्यवाद, क्या पसंद करने के लिए कोई परिस्थिति है। (1) ओवर .टेल, या इसके विपरीत?
गाविलन कोमुन

8
@ जेम्स पेट्री - यदि आप tailएक खाली सूची पर कॉल करते हैं तो आपको एक अपवाद मिलता है scala> List().tail java.lang.UnsupportedOperationException: tail of empty list:। drop(1)एक खाली सूची पर हालांकि एक खाली सूची देता है।
फ्रैंक एस। थॉमस

3
tailयदि सूची खाली है (यानी कोई नहीं है head) तो एक अपवाद फेंकता है । drop(1)खाली सूची में सिर्फ एक और खाली सूची मिलती है।
रेक्स केर

8

दुर्भाग्य से, संग्रह पदानुक्रम के साथ थोड़ा गड़बड़ हो गया - गया List। के लिए ArrayBufferयह काम करता है, जैसा कि आपने आशा हो सकता है:

scala> collection.mutable.ArrayBuffer(1,2,3,2,4) - 2
res0: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 3, 2, 4)

लेकिन, दुख की बात है, Listएक filterNot-स्टाइल कार्यान्वयन के साथ समाप्त हो गया और इस तरह "गलत काम" होता है और आप पर एक चेतावनी चेतावनी फेंक देता है (समझदार पर्याप्त, क्योंकि यह वास्तव में filterNotआईएनजी है):

scala> List(1,2,3,2,4) - 2                          
warning: there were deprecation warnings; re-run with -deprecation for details
res1: List[Int] = List(1, 3, 4)

तो यकीनन करने के लिए सबसे आसान काम Listएक संग्रह में परिवर्तित होता है जो इस अधिकार को करता है, और फिर वापस फिर से परिवर्तित करें:

import collection.mutable.ArrayBuffer._
scala> ((ArrayBuffer() ++ List(1,2,3,2,4)) - 2).toList
res2: List[Int] = List(1, 3, 2, 4)

वैकल्पिक रूप से, आप अपने द्वारा प्राप्त कोड का तर्क रख सकते हैं लेकिन शैली को अधिक मुहावरेदार बना सकते हैं:

def removeInt(i: Int, li: List[Int]) = {
  def removeOne(i: Int, left: List[Int], right: List[Int]): List[Int] = right match {
    case r :: rest =>
      if (r == i) left.reverse ::: rest
      else removeOne(i, r :: left, rest)
    case Nil => left.reverse
  }
  removeOne(i, Nil, li)
}

scala> removeInt(2, List(1,2,3,2,4))
res3: List[Int] = List(1, 3, 2, 4)

removeInt(5,List(1,2,6,4,5,3,6,4,6,5,1))पैदावार List(4, 6, 2, 1, 3, 6, 4, 6, 5, 1)। मुझे लगता है कि यह वह नहीं है जो आप चाहते थे।
केन ब्लूम

@ केन ब्लूम - वास्तव में। यह मूल एल्गोरिथ्म में एक त्रुटि है, जिसे मैंने बिना सोचे-समझे कॉपी कर लिया। अभी तय किया है।
रेक्स केर

प्रश्न विशेष में अधिक चूक, क्योंकि मेरे विशिष्ट मामले में आदेश मायने नहीं रखता। आदेश-संरक्षण संस्करण को देखने के लिए अच्छा है, धन्यवाद।
गाविलन कोमुन

@Rex: 'फ़िल्टरनोट' से क्या मतलब है "गलत काम"? कि यह सभी घटनाओं को हटा रहा है? और यह एक डिप्रेसेशन चेतावनी क्यों देता है? धन्यवाद
टेओ

1
@teo - यह सभी घटनाओं को हटाता है (जो कि यहां वांछित नहीं है), और इसे हटा दिया गया है क्योंकि यह यकीनन टूट गया है (या शायद वांछित व्यवहार स्पष्ट नहीं है - या तो, यह 2.9 में पदावनत है और 2.10 में चला गया है)।
रेक्स केर


2

कैसा रहेगा

def removeCard(c: Card, cards: List[Card]) = {
  val (head, tail) = cards span {c!=}   
  head ::: 
  (tail match {
    case x :: xs => xs
    case Nil => Nil
  })
}

अगर आप देखें return, तो कुछ गड़बड़ है।


1
यह वह नहीं करता है जो वह चाहता है, जो c
केन ब्लूम

1
यह सभी कार्डों को हटा देगा c, लेकिन केवल पहले हटा दिया जाना चाहिए।
दसवीं

मुझे प्रश्नों को अधिक ध्यान से पढ़ना चाहिए! मेरे उत्तर को सही किया।
यूजीन योकोटा

+1 के लिए "यदि आप रिटर्न देखते हैं, तो कुछ गड़बड़ है।" यह अपने आप में एक बहुत ही महत्वपूर्ण "मुहावरा स्काला" सबक है।
जो कैरनहान


1

एक संभव समाधान के रूप में आप पहले उपयुक्त तत्व का सूचकांक पा सकते हैं और फिर इस सूचकांक पर तत्व को हटा सकते हैं:

def removeOne(l: List[Card], c: Card) = l indexOf c match {
    case -1 => l
    case n => (l take n) ++ (l drop (n + 1))
}

spanएक ही काम करने के लिए मेरा जवाब देखें ।
केन ब्लूम

0

तह का उपयोग करके ऐसा करने के बारे में बस एक और विचार:

def remove[A](item : A, lst : List[A]) : List[A] = {
    lst.:\[List[A]](Nil)((lst, lstItem) => 
       if (lstItem == item) lst else lstItem::lst )
}

0

सामान्य पूंछ पुनरावृत्ति समाधान:

def removeElement[T](list: List[T], ele: T): List[T] = {
    @tailrec
    def removeElementHelper(list: List[T],
                            accumList: List[T] = List[T]()): List[T] = {
      if (list.length == 1) {
        if (list.head == ele) accumList.reverse
        else accumList.reverse ::: list
      } else {
        list match {
          case head :: tail if (head != ele) =>
            removeElementHelper(tail, head :: accumList)
          case head :: tail if (head == ele) => (accumList.reverse ::: tail)
          case _                             => accumList
        }
      }
    }
    removeElementHelper(list)
  }


-4
object HelloWorld {

    def main(args: Array[String]) {

        var months: List[String] = List("December","November","October","September","August", "July","June","May","April","March","February","January")

        println("Deleting the reverse list one by one")

        var i = 0

        while (i < (months.length)){

            println("Deleting "+months.apply(i))

            months = (months.drop(1))

        }

        println(months)

    }

}

क्या आप कृपया कुछ स्पष्टीकरण (टिप्पणियाँ, विवरण) जोड़ सकते हैं कि यह प्रश्न का उत्तर कैसे देता है?
19

4
1. यह सवाल 5 साल पहले पूछा गया था और इसका जवाब दिया गया था। 2. ओपी ने "मुहावरेदार" स्काला के लिए कहा। 2 varएस और एक whileलूप का उपयोग करना मुहावरेदार स्काला नहीं है।
jwvh
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.