如何在 Scala 中使用地图并接收索引?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2213323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I use map and receive an index as well in Scala?
提问by Geo
Is there any List/Sequence built-in that behaves like mapand provides the element's index as well?
是否有任何内置的 List/Sequence 行为类似于map并提供元素的索引?
回答by Viktor Klang
I believe you're looking for zipWithIndex?
我相信您正在寻找 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
From: http://www.artima.com/forums/flat.jsp?forum=283&thread=243570
来自:http: //www.artima.com/forums/flat.jsp?forum=283& thread=243570
You also have variations like:
您还有变体,例如:
for((e,i) <- List("Mary", "had", "a", "little", "lamb").zipWithIndex) println(i+" "+e)
or:
或者:
List("Mary", "had", "a", "little", "lamb").zipWithIndex.foreach( (t) => println(t._2+" "+t._1) )
回答by Paulo Cheque
Use .mapin .zipWithIndex
利用 。映射在 . 带索引的zip
val myList = List("a", "b", "c")
myList.zipWithIndex.map { case (element, index) =>
println(element, index)
s"${element}(${index})"
}
Result:
结果:
List("a(0)", "b(1)", "c(2)")
回答by Matt Brasen
The proposed solutions suffer from the fact that they create intermediate collections or introduce variables which are not strictly necessary. For ultimately all you need to do is to keep track of the number of steps of an iteration. This can be done using memoizing. The resulting code might look like
所提出的解决方案受到以下事实的影响:它们创建了中间集合或引入了并非绝对必要的变量。最终您需要做的就是跟踪迭代的步骤数。这可以使用记忆来完成。结果代码可能看起来像
myIterable map (doIndexed(someFunction))
The doIndexed-Function wraps the interior function which receives both an index an the elements of myIterable. This might be familiar to you from JavaScript.
的doIndexed-功能包,其接收两个的索引的的元素的内部功能myIterable。您可能对 JavaScript 很熟悉。
Here is a way to achieve this purpose. Consider the following utility:
这是实现此目的的方法。考虑以下实用程序:
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)
}
}
This is already all you need. You can apply this for instance as follows:
这已经是你所需要的。例如,您可以按如下方式应用:
import TraversableUtil._
List('a','b','c').map(doIndexed((i, char) => char + i))
which results in the list
这导致列表
List(97, 99, 101)
This way, you can use the usual Traversable-functions at the expense of wrapping your effective function. The overhead is the creation of the memoizing object and the counter therein. Otherwise this solution is as good (or bad) in terms of memory or performance as using unindexed map. Enjoy!
这样,您可以使用通常的 Traversable 函数,但代价是包装您的有效函数。开销是创建记忆对象和其中的计数器。否则,此解决方案在内存或性能方面与使用 unindexed 一样好(或不好)map。享受!
回答by Rex Kerr
There is CountedIteratorin 2.7.x (which you can get from a normal iterator with .counted). I believe it's been deprecated (or simply removed) in 2.8, but it's easy enough to roll your own. You do need to be able to name the iterator:
有CountedIterator在2.7.x(你可以从一个正常的迭代器获取与.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)
回答by Cristian Vrabie
Or, assuming your collection has constant access time, you could map the list of indexes instead of the actual collection:
或者,假设您的集合具有恒定的访问时间,您可以映射索引列表而不是实际集合:
val ls = List("a","b","c")
0.until(ls.length).map( i => doStuffWithElem(i,ls(i)) )
回答by fgfernandez0321
Use .mapin .zipWithIndexwith Map data structure
在.zipWithIndex 中使用.map和 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"
}
Results
结果
List(
Key: a - Value: hello with Index: 0,
Key: b - Value: world with Index: 1,
Key: c - Value: again with Index: 2
)
回答by Madstuffs
There are two ways of doing this.
有两种方法可以做到这一点。
ZipWithIndex:Creates a counter automatically starting with 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")
}
Output of both code will be:
两个代码的输出将是:
0 is Sun
1 is Mon
2 is Tue
3 is Wed
4 is Thu
5 is Fri
6 is Sat
Zip: Use zip method with a Stream to create a counter. This gives you a way to control the starting value.
Zip:将 zip 方法与 Stream 一起使用以创建计数器。这为您提供了一种控制起始值的方法。
for ((day, count) <- days.zip(Stream from 1)) {
println(s"$count is $day")
}
Result:
结果:
1 is Sun
2 is Mon
3 is Tue
4 is Wed
5 is Thu
6 is Fri
7 is Sat
回答by Yair Beer
If you require searching the map values as well (like I had to):
如果您还需要搜索地图值(就像我必须的那样):
val ls = List("a","b","c")
val ls_index_map = ls.zipWithIndex.toMap

