어떻게지도를 사용하고 Scala에서도 인덱스를받을 수 있습니까?


답변:


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 2012 년

예를 들어 while가장 빠른 옵션 중 하나 인 루프와 비교합니다 .
ziggystar

Array 및 while 루프는 가능한 한 빠릅니다.
Viktor Klang 2012 년

2
@ziggystar 성능을 찾고 있다면 불변성을 절충해야합니다. zipWithIndex 함수 내부를 살펴보십시오. 단지 var를 사용하여 새로운 쌍 모음을 만듭니다. Java에서와 마찬가지로 새 컬렉션을 빌드하지 않고도 var를 증가시키는 동일한 방법을 사용할 수 있습니다. 그러나 그것은 기능적인 스타일이 아닙니다. 실제로 필요한지 생각하십시오.
Cristian Vrabie 2012 년

따라서 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
이것은 .NET map내부에 인쇄하는 대신 요청 된 대로 를 사용한 첫 번째 괜찮은 예 foreach입니다.
그렉 Chabala

10

제안 된 솔루션은 중간 컬렉션을 생성하거나 엄격하게 필요하지 않은 변수를 도입한다는 사실로 어려움을 겪습니다. 궁극적으로해야 할 일은 반복 단계 수를 추적하는 것입니다. 이것은 메모를 사용하여 수행 할 수 있습니다. 결과 코드는 다음과 같습니다.

myIterable map (doIndexed(someFunction))

doIndexedα- 함수 인덱스 요소 모두를 수신하는 기능을 내부 랩 myIterable. 이것은 JavaScript에서 친숙 할 것입니다.

이 목적을 달성하는 방법이 있습니다. 다음 유틸리티를 고려하십시오.

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)

이렇게하면 효과적인 함수를 래핑하는 대신 일반적인 Traversable 함수를 사용할 수 있습니다. 오버 헤드는 메모 개체와 그 안에 카운터를 만드는 것입니다. 그렇지 않으면이 솔루션은 unindexed를 사용하는 것만 큼 메모리 나 성능면에서 좋거나 나쁩니다 map. 즐겨!


1
이것은 문제에 대한 매우 우아한 해결책입니다. 임시 컬렉션을 만들지 않은 경우 +1. 병렬 컬렉션에서는 작동하지 않지만 여전히 매우 좋은 솔루션입니다.
fbl

5
임시 컬렉션을 만들 싶지 않아, 그냥 사용하는 coll.view.zipWithIndex대신에coll.zipWithIndex
츠나

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
Cristian Vrabie

1
때문에 복잡성 downvote - LS로 반복 (i)는 (N ^ 2) O 얻어
모세 Bixenshpaner

1
@MosheBixenshpaner 충분합니다. 나의 예 List는 참으로 가난했습니다. 그러나 컬렉션에 일정한 액세스 시간이있는 경우 이것이 적합하다고 언급했습니다. 을 선택해야합니다 Array.
Cristian Vrabie

1

지도 데이터 구조와 함께 .zipWithIndex 에서 .map 사용

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

Zip : Stream과 함께 zip 방식을 사용하여 카운터를 생성합니다. 이것은 시작 값을 제어하는 ​​방법을 제공합니다.

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 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.