在scala中为无后减量的序列分配序数

在scala中为无后减量的序列分配序数,scala,Scala,由于我是scala的新手,我在谷歌上搜索了很多东西,在大多数情况下都能找到好的答案。但我找不到这个具体问题的答案,因为谷歌搜索“scala中的后减量”只会让dontcha-use-post-decrement-in-scala-because-its-a-functional-language-answers排名靠前 所以,我真的想知道做以下事情的功能方式是什么: object A { val list = List("a", "b", "c") val map = { var

由于我是scala的新手,我在谷歌上搜索了很多东西,在大多数情况下都能找到好的答案。但我找不到这个具体问题的答案,因为谷歌搜索“scala中的后减量”只会让dontcha-use-post-decrement-in-scala-because-its-a-functional-language-answers排名靠前

所以,我真的想知道做以下事情的功能方式是什么:

object A {
  val list = List("a", "b", "c")
  val map = {
    var ord = list.size
    Map(list map { x => (x, { val res = ord; ord -= 1; res } ) } : _* )
  }
}

class Test extends org.scalatest.FunSuite {
  test("") {
    println(A.map) // Map(a -> 3, b -> 2, c -> 1)
  }
}
它基本上是从给定的列表中创建一个映射,并为列表中的每个元素分配递减的序号(实际代码当然比这个最小的示例更复杂)


我对
var-ord=…
(可变)和
{val-res=ord;ord-=1;res}
(减量后)部分特别不满意:/还有其他(更漂亮的)方法吗?

你可以简单地写下:

 val list = List("a","b","c")
 list.map ( elem => (elem, list.size - list.indexOf(elem))).toMap
它将为您提供如下结果:

scala.collection.immutable.Map[String,Int] = Map(a -> 3, b -> 2, c -> 1)

快速解决方案需要颠倒列表,然后您可以使用
zipWithIndex

scala> :pa
// Entering paste mode (ctrl-D to finish)

List("a", "b", "c")
  .reverse
  .zipWithIndex
  .toMap

// Exiting paste mode, now interpreting.

res4: scala.collection.immutable.Map[String,Int] = Map(c -> 0, b -> 1, a -> 2)
如果您不介意额外集合的分配,您可以删除
视图

这一点很有帮助

list.reverse.zip(1 to list.size + 1).toMap
试试这个:

list.toIterator.zip(Iterator.iterate(list.size){_-1}).toMap

还有另一种变体

list.zip(list.size to 1 by -1).toMap

性能类似于
.reverse.zipWithIndex
,因为
reverse
size
都是O(N)

如果两个元素具有相同的值,则会失败。另外,
indexOf
是O(N),所以这是毫无意义的慢。虽然公平地说,如果两个元素具有相同的值,OP想要什么还不清楚……我知道,但根据你的问题,我给出了解决方案,但你想多次使用相同的键创建一个映射吗?试试这个(i第二个
反转
是不必要的,因为
映射
@TheArchetypalPaul我同意,但我希望示例以OP希望的方式打印出来。也许我应该删除它。@YuvalItzchakov我知道地图没有被排序;)Map的打印顺序只是一个实现工件。我认为,显然说一个人可以可靠地定义order@Alex
zipWithIndex
索引从
0
开始,您需要手动
zip
或添加一个额外的:
.map(t=>(t.\u 1,t.\u 2+1)
zipWithIndex
之后。您不需要
+1