स्केल सूची बनाने का पसंदीदा तरीका


117

स्काला में एक अपरिवर्तनीय सूची बनाने के कई तरीके हैं (नीचे दिए गए उदाहरण कोड देखें)। आप एक उत्परिवर्ती ListBuffer का उपयोग कर सकते हैं, एक varसूची बना सकते हैं और इसे संशोधित कर सकते हैं, एक पूंछ पुनरावर्ती विधि का उपयोग कर सकते हैं , और शायद अन्य जिनके बारे में मुझे जानकारी नहीं है।

सहज रूप से, मैं ListBuffer का उपयोग करता हूं, लेकिन मेरे पास ऐसा करने का एक अच्छा कारण नहीं है। क्या एक सूची बनाने के लिए एक पसंदीदा या मुहावरेदार तरीका है, या क्या ऐसी परिस्थितियां हैं जो एक विधि से दूसरे के लिए सर्वोत्तम हैं?

import scala.collection.mutable.ListBuffer

// THESE are all the same as: 0 to 3 toList.
def listTestA() ={
    var list:List[Int] = Nil

    for(i <- 0 to 3) 
        list = list ::: List(i)
    list
}


def listTestB() ={
    val list = new ListBuffer[Int]()

    for (i <- 0 to 3) 
        list += i
    list.toList
}


def listTestC() ={
    def _add(l:List[Int], i:Int):List[Int] = i match {
        case 3 => l ::: List(3)
        case _ => _add(l ::: List(i), i +1)
    }
    _add(Nil, 0)
}

जवाबों:


108

ListBufferएक परिवर्तनशील सूची है जिसमें निरंतर-समय का परिशिष्ट है, और निरंतर-समय रूपांतरण में है List

List अपरिवर्तनीय है और इसमें निरंतर-समय का प्रीपेंड और लीनियर-टाइम एपेंड है।

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

उदाहरण के लिए, यदि आप तत्वों को विपरीत क्रम में प्राप्त करते हैं, जब वे उपयोग होने जा रहे हैं, तो आप बस एक का उपयोग कर सकते हैं Listऔर प्रीपेंड कर सकते हैं । चाहे आप एक पूंछ-पुनरावर्ती फ़ंक्शन के साथ ऐसा करेंगे foldLeft, या कुछ और वास्तव में प्रासंगिक नहीं है।

यदि आप उसी क्रम में तत्वों को प्राप्त करते हैं जो आप उनका उपयोग करते हैं, तो ListBufferसबसे अधिक संभावना एक बेहतर विकल्प है, यदि प्रदर्शन महत्वपूर्ण है।

लेकिन, यदि आप एक महत्वपूर्ण पथ पर नहीं हैं और इनपुट काफी कम है, तो आप reverseसूची को बाद में या बस foldRightया reverseइनपुट पर ले सकते हैं, जो कि रैखिक समय है।

आप जो नहीं करते हैं वह इसका उपयोग करता है Listऔर इसे जोड़ता है। यह आपको केवल अंत में प्रस्तुत करने और उलटने की तुलना में बहुत खराब प्रदर्शन देगा।


What you DON'T do is use a List and append to itक्या इसलिए कि एक नई सूची बन जाती है? जबकि, प्रीपेन्ड ऑपरेशन का उपयोग करने से नई सूची नहीं बनेगी?
केविन मेरेडिथ

2
@KevinMeredith हाँ। परिशिष्ट O (n) है, Prepend O (1) है।
डैनियल सी। सोबरल

@pgoggijr यह सच नहीं है। सबसे पहले, कहीं भी "परिवर्तन" नहीं है, क्योंकि यह अपरिवर्तनीय है। एक ट्रावर्सल की आवश्यकता होती है क्योंकि सभी तत्वों को कॉपी करना होता है, बस इसलिए अंतिम तत्व की एक कॉपी के बजाय एक नए सिस्टम की ओर इशारा किया जा सकता है Nil। दूसरा, प्रीपेन्ड पर किसी प्रकार की कोई प्रतिलिपि नहीं है: मौजूदा सूची की ओर इशारा करते हुए एक तत्व बनाया गया है, और यह बात है।
डैनियल सी। सोबरल


22

उम्म्म .. ये मुझे बहुत जटिल लगते हैं। क्या मैं प्रस्ताव कर सकता हूँ?

def listTestD = (0 to 3).toList

या

def listTestE = for (i <- (0 to 3).toList) yield i

उत्तर के लिए धन्यवाद, लेकिन सवाल यह है कि आप गैर-तुच्छ मामले में क्या करते हैं। मैंने कोड में एक टिप्पणी डालते हुए बताया कि वे सभी 0 से 3 के बराबर थे।
agilefall

उफ़, क्षमा करें! सच कहूँ तो, मैं कभी भी ListBuffer का उपयोग नहीं करता।
अलेक्जेंडर अजरोव

5

आप किसी भी संस्करण को समाप्त करके आमतौर पर स्काला में अपरिवर्तनीयता पर ध्यान केंद्रित करना चाहते हैं। आपके साथी आदमी के लिए पठनीयता अभी भी महत्वपूर्ण है:

प्रयत्न:

scala> val list = for(i <- 1 to 10) yield i
list: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

आप शायद ज्यादातर मामलों में एक सूची में बदलने की जरूरत नहीं है :)

अनुक्रमित seq में आपकी ज़रूरत की हर चीज़ होगी:

यानी अब आप उस IndexedSeq पर काम कर सकते हैं:

scala> list.foldLeft(0)(_+_)
res0: Int = 55

एनबी Vectorअब डिफ़ॉल्ट Seqकार्यान्वयन भी है ।
कॉनर डॉयल

2

मैं हमेशा सूची पसंद करता हूं और मैं "समझ के लिए" से पहले "गुना / कम" का उपयोग करता हूं। हालांकि, "समझ के लिए" पसंद किया जाता है अगर नेस्टेड "सिलवटों" की आवश्यकता होती है। यदि मैं "फोल्ड / कम / फॉर" का उपयोग करके कार्य पूरा नहीं कर सकता तो रिकर्सियन अंतिम उपाय है।

आपके उदाहरण के लिए, मैं करूँगा:

((0 to 3) :\ List[Int]())(_ :: _)

मेरे करने से पहले:

(for (x <- 0 to 3) yield x).toList

नोट: मैं "_L" के आदेश के कारण "foldLeft (/ :)" के स्थान पर "foldRight (: \)" का उपयोग करता हूं। ऐसे संस्करण के लिए जो StackOverflowException को नहीं फेंकता है, इसके बजाय "foldLeft" का उपयोग करें।


18
मैं दृढ़ता से असहमत हूँ; आपका पसंदीदा रूप सिर्फ लाइन शोर जैसा दिखता है।
मैट आर

14
क्या मैं? मैंने पहली बार हास्केल 1999 में सीखा, और कुछ वर्षों तक स्काला में डबिंग करता रहा। मुझे लगता है कि सिलवटों का उपयोग बहुत अच्छा है, लेकिन अगर किसी भी स्थिति में एक गुना लागू करने के लिए विराम चिह्नों के एक गुप्त स्ट्रिंग को लिखने की आवश्यकता होती है, तो मैं एक अलग दृष्टिकोण पर विचार करूंगा।
मैट आर

11
@ मत्त आर: मैं सहमत हूं। इसमें अति करने जैसी बात है, और यह उनमें से एक है।
रयगी

8
@AlterChang मुझे उन सभी इमोटिकॉन्स का लुक पसंद है। एक मिनट रुकिए, क्या वह कोड है? : पी
डेविड जे।

4
क्या ((0 to 3) :\ List[Int]())(_ :: _)इमोटिकोड को कॉल करना उचित है ?
डेविड जे।

2

List.tabulateइस तरह का उपयोग करना ,

List.tabulate(3)( x => 2*x )
res: List(0, 2, 4)

List.tabulate(3)( _ => Math.random )
res: List(0.935455779102479, 0.6004888906328091, 0.3425278797788426)

List.tabulate(3)( _ => (Math.random*10).toInt )
res: List(8, 0, 7)

2

नोट: यह उत्तर स्काला के पुराने संस्करण के लिए लिखा गया है।

स्काला संग्रह वर्गों को स्केल 2.8 के रूप में नया रूप दिया जा रहा है, इसलिए बहुत जल्द सूची बनाने के तरीके को बदलने के लिए तैयार रहें।

सूची बनाने का आगे का संगत तरीका क्या है? मुझे कोई पता नहीं है क्योंकि मैंने अभी तक 2.8 डॉक्स नहीं पढ़ा है।

एक पीडीएफ दस्तावेज़, संग्रह कक्षाओं के प्रस्तावित परिवर्तनों का वर्णन करता है


2
ज्यादातर बदलाव आंतरिक चीजों को लागू करने के तरीके और अनुमानों जैसी उन्नत चीजों में हैं। आप एक सूची कैसे बनाते हैं वह प्रभावित नहीं होती है।
मार्कस डाउनिंग

ठीक है, यह जानना अच्छा है। यदि आप संग्रह में किसी भी वर्ग का उपयोग करते हैं तो आप भी प्रभावित होंगे। jcl पैकेज।
एंड्रे लास्ज़लो

1

नए स्कैला डेवलपर के रूप में, मैंने ऊपर दिए गए तरीकों के साथ सूची निर्माण समय की जांच करने के लिए छोटा परीक्षण लिखा। यह ऐसा लगता है ((p <- (0 से x)) उपज p) सबसे तेज़ दृष्टिकोण के लिए।

import java.util.Date
object Listbm {

  final val listSize = 1048576
  final val iterationCounts = 5
  def getCurrentTime: BigInt = (new Date) getTime

  def createList[T] ( f : Int => T )( size : Int ): T = f ( size )

  // returns function time execution
  def experiment[T] ( f : Int => T ) ( iterations: Int ) ( size :Int ) : Int  = {

    val start_time = getCurrentTime
    for ( p <- 0 to iterations )  createList ( f ) ( size )
    return (getCurrentTime - start_time) toInt

  }

  def printResult ( f:  => Int ) : Unit = println ( "execution time " + f  )

  def main( args : Array[String] ) {


    args(0) match {

      case "for" =>  printResult ( experiment ( x => (for ( p <- ( 0 to x ) ) yield p) toList  ) ( iterationCounts ) ( listSize ) )
      case "range"  =>  printResult ( experiment ( x => ( 0 to x ) toList ) ( iterationCounts ) ( listSize ) )
      case "::" => printResult ( experiment ( x => ((0 to x) :\ List[Int]())(_ :: _) ) ( iterationCounts ) ( listSize ) )
      case _ => println ( "please use: for, range or ::\n")
    }
  }
}

0

सिर्फ एक उदाहरण जो collection.breakOut का उपयोग करता है

scala> val a : List[Int] = (for( x <- 1 to 10 ) yield x * 3)(collection.breakOut)
a: List[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27, 30)

scala> val b : List[Int] = (1 to 10).map(_ * 3)(collection.breakOut)
b: List[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27, 30)

0

स्ट्रिंग की सूची बनाने के लिए, निम्नलिखित का उपयोग करें:

val l = List("is", "am", "are", "if")

1
एक प्रश्न का उत्तर देते समय यह पुराना (10 वर्ष), और इतने सारे मौजूदा उत्तरों (9) के साथ, यह समझाने के लिए एक अच्छा अभ्यास है कि आपका उत्तर अन्य सभी से अलग क्यों है। जैसा कि यह है, ऐसा लगता है कि आपने प्रश्न को नहीं समझा।
jwvh
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.