मैं मानचित्र का उपयोग कैसे कर सकता हूं और स्कैला में एक सूचकांक भी प्राप्त कर सकता हूं?


99

क्या कोई सूची / अनुक्रम अंतर्निहित है जो व्यवहार करता है mapऔर तत्व के सूचकांक को भी प्रदान करता है?

जवाबों:


148

मेरा मानना ​​है कि आप zipWithIndex की तलाश कर रहे हैं?

scala> val ls = List("Mary", "had", "a", "little", "lamb")
scala> ls.zipWithIndex.foreach{ case (e, i) => println(i+" "+e) }
0 Mary
1 had
2 a
3 little
4 lamb

प्रेषक: http://www.artima.com/forums/flat.jsp?forum=283&thread=243570

आपके पास भी भिन्नताएं हैं:

for((e,i) <- List("Mary", "had", "a", "little", "lamb").zipWithIndex) println(i+" "+e)

या:

List("Mary", "had", "a", "little", "lamb").zipWithIndex.foreach( (t) => println(t._2+" "+t._1) )

4
ठीक है, मैं zipWithIndexएक पाश / नक्शा / जो कुछ भी अंदर सूचकांक प्राप्त करने के लिए विधि का उपयोग करना था ।
ziggystar

उदाहरण के लिए एक whileलूप की तुलना करना , जो संभवतः सबसे तेज़ विकल्पों में से है।
जिग्गीस्टार

एक सरणी और थोड़ी देर का लूप शायद उतना ही तेज़ है जितना कि यह मिल सकता है।
विक्टर क्लैंग

2
@ziggystar यदि आप प्रदर्शन के लिए देख रहे हैं तो आपको कुछ अपरिवर्तनीयता का व्यापार करने की आवश्यकता है। ZipWithIndex फ़ंक्शन के अंदर देखें। यह सिर्फ जोड़े के नए संग्रह के निर्माण के लिए एक संस्करण का उपयोग करता है। आप नए संग्रह के निर्माण के बिना एक संस्करण को बढ़ाने के उसी तरीके का उपयोग कर सकते हैं, जैसा कि आप जावा में करते हैं। लेकिन यह कार्यात्मक शैली नहीं है। सोचें कि क्या आपको वास्तव में इसकी आवश्यकता है।
क्रिस्टियन व्राबी

तो यह भी zipWithIndex ही कार्यात्मक शैली नहीं है लगता है। वैसे भी मुझे लगता है कि यह उल्लेख किया जाना चाहिए कि viewआपको एक अतिरिक्त सूची बनाने और ट्रेस करने से रोकने में सक्षम होना चाहिए।
हरमन

55

उपयोग । नक्शा में। zipWithIndex

val myList = List("a", "b", "c")

myList.zipWithIndex.map { case (element, index) => 
   println(element, index) 
   s"${element}(${index})"
}

परिणाम:

List("a(0)", "b(1)", "c(2)")

11
यह पहला सभ्य उदाहरण है जो मैंने देखा है कि mapकेवल एक मुद्रण के बजाय एक अनुरोध के रूप में इस्तेमाल किया foreach
ग्रेग चबाला

10

प्रस्तावित समाधान इस तथ्य से पीड़ित हैं कि वे मध्यवर्ती संग्रह बनाते हैं या चर का परिचय देते हैं जो कड़ाई से आवश्यक नहीं हैं। अंततः आपको केवल एक पुनरावृत्ति के चरणों की संख्या का ट्रैक रखना है। यह मेमोइज़िंग का उपयोग करके किया जा सकता है। परिणामी कोड की तरह लग सकता है

myIterable map (doIndexed(someFunction))

doIndexedसमारोह आंतरिक समारोह जो दोनों एक सूचकांक एक के तत्वों को प्राप्त करता है लपेटता myIterable। यह आपको जावास्क्रिप्ट से परिचित हो सकता है।

यहाँ इस उद्देश्य को प्राप्त करने का एक तरीका है। निम्नलिखित उपयोगिता पर विचार करें:

object TraversableUtil {
    class IndexMemoizingFunction[A, B](f: (Int, A) => B) extends Function1[A, B] {
        private var index = 0
        override def apply(a: A): B = {
            val ret = f(index, a)
            index += 1
            ret
        }
    }

    def doIndexed[A, B](f: (Int, A) => B): A => B = {
        new IndexMemoizingFunction(f)
    }
}

यह पहले से ही आप सभी की जरूरत है। आप इसे इस प्रकार लागू कर सकते हैं:

import TraversableUtil._
List('a','b','c').map(doIndexed((i, char) => char + i))

जिसका परिणाम सूची में है

List(97, 99, 101)

इस तरह, आप अपने प्रभावी फ़ंक्शन को लपेटने की कीमत पर सामान्य ट्रैवर्सेबल-फ़ंक्शंस का उपयोग कर सकते हैं। ओवरहेड मेमोइज़िंग ऑब्जेक्ट और उसमें काउंटर का निर्माण है। अन्यथा यह समाधान याददाश्त या प्रदर्शन के मामले में उतना ही अच्छा (या बुरा) है जैसा कि अनइंडेक्स का उपयोग करना map। का आनंद लें!


1
यह समस्या का एक बहुत ही सुंदर समाधान है। अस्थायी संग्रह नहीं बनाने के लिए +1। एक समानांतर संग्रह में काम नहीं करेगा, लेकिन अभी भी एक बहुत अच्छा समाधान है।
13:14 पर 13:14 बजे fbl

5
यदि आप एक अस्थायी संग्रह नहीं बनाना चाहते हैं, तो coll.view.zipWithIndexइसके बजाय का उपयोग करेंcoll.zipWithIndex
tsuna

5

नहीं है CountedIterator(जो आप एक सामान्य पुनरावर्तक से प्राप्त कर सकते हैं .counted के साथ) 2.7.x में। मेरा मानना ​​है कि यह 2.8 में पदावनत (या बस हटा दिया गया) है, लेकिन यह अपने स्वयं के रोल करने के लिए पर्याप्त आसान है। आपको इट्रेटर का नाम देने में सक्षम होने की आवश्यकता है:

val ci = List("These","are","words").elements.counted
scala> ci map (i => i+"=#"+ci.count) toList
res0: List[java.lang.String] = List(These=#0,are=#1,words=#2)

3

या, मान लें कि आपके संग्रह में निरंतर पहुंच का समय है, तो आप वास्तविक संग्रह के बजाय अनुक्रमित की सूची को मैप कर सकते हैं:

val ls = List("a","b","c")
0.until(ls.length).map( i => doStuffWithElem(i,ls(i)) )

1
यह करने के लिए एक और अधिक सुंदर तरीका बस है: ls.indices.map(i => doStuffWithElem(i, ls(i))
Assil Ksiksi

3
@aksiksi ठीक है, यह देखते हुए कि यह बहुत हद तक एक ही चीज के indicesरूप में लागू किया0 until length गया है: P
क्रिस्टियन Vrabie

1
नीचे की वजह से जटिलता - ls के साथ पुनरावृत्ति (i) लेता है O (n ^ 2)
मोशे बिक्सेनस्पैन

1
@MosheBixenshpaner मेला काफी मेरा उदाहरण Listवास्तव में गरीब था। मैंने हालांकि यह उल्लेख किया कि यह उपयुक्त है यदि आपके संग्रह में निरंतर पहुंच का समय है। उठा लेना चाहिए था Array
क्रिस्टियन Vrabie

1

का प्रयोग करें .map में .zipWithIndex मानचित्र डेटा संरचना के साथ

val sampleMap = Map("a" -> "hello", "b" -> "world", "c" -> "again")

val result = sampleMap.zipWithIndex.map { case ((key, value), index) => 
    s"Key: $key - Value: $value with Index: $index"
}

परिणाम

 List(
       Key: a - Value: hello with Index: 0, 
       Key: b - Value: world with Index: 1, 
       Key: c - Value: again with Index: 2
     )

1

इसे करने के दो तरीके हैं।

ZipWithIndex: स्वचालित रूप से 0 से शुरू होने वाला एक काउंटर बनाता है।

  // zipWithIndex with a map.
  val days = List("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
  days.zipWithIndex.map {
        case (day, count) => println(s"$count is $day")
  }
  // Or use it simply with a for.
  for ((day, count) <- days.zipWithIndex) {
        println(s"$count is $day")
  }

दोनों कोड का आउटपुट होगा:

0 is Sun
1 is Mon
2 is Tue
3 is Wed
4 is Thu
5 is Fri
6 is Sat

ज़िप : काउंटर बनाने के लिए स्ट्रीम के साथ ज़िप विधि का उपयोग करें। यह आपको शुरुआती मूल्य को नियंत्रित करने का एक तरीका देता है।

for ((day, count) <- days.zip(Stream from 1)) {
  println(s"$count is $day")
}

परिणाम:

1 is Sun
2 is Mon
3 is Tue
4 is Wed
5 is Thu
6 is Fri
7 is Sat

0

यदि आपको मानचित्र मानों को खोजने की आवश्यकता है (जैसे मुझे करना था):

val ls = List("a","b","c")
val ls_index_map = ls.zipWithIndex.toMap 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.