如何在Scala中使用map并接收索引?

时间:2010-02-06 13:59:47

标签: scala functional-programming map

是否有任何内置的List / Sequence,其行为类似于map并且还提供了元素的索引?

8 个答案:

答案 0 :(得分:136)

我相信你正在寻找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) )

答案 1 :(得分:47)

使用。地图 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)")

答案 2 :(得分:8)

提出的解决方案受制于这样的事实,即它们创建中间集合或引入非严格必要的变量。最终,您需要做的就是跟踪迭代的步骤数。这可以使用memoizing完成。生成的代码可能看起来像

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函数,但代价是包装有效函数。开销是在其中创建记忆对象和计数器。否则,此解决方案在内存或性能方面与使用未编制索引map一样好(或差)。享受!

答案 3 :(得分:5)

2.7.x中有CountedIterator(你可以从.counted的普通迭代器中获得)。我相信它在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)

答案 4 :(得分:3)

或者,假设您的集合具有持续访问时间,您可以映射索引列表而不是实际集合:

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

答案 5 :(得分:0)

如果您还需要搜索地图值(就像我必须的那样):

val ls = List("a","b","c")
val ls_index_map = ls.zipWithIndex.toMap 

答案 6 :(得分:0)

.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
     )

答案 7 :(得分:0)

有两种方法。

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方法与流一起使用以创建计数器。这为您提供了一种控制初始值的方法。

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