如何获取 SortedSet 中项目的索引
How to get the index of an item in a SortedSet
我正在实施某种 "record matrix",其中轴索引是某种类型 K
(例如字符串)的(唯一)键。这些键不需要排序,但我需要一个顺序,所以我选择了一个 SortedSet。
键 (SortedSet) 的主要目的是在底层二维数据数组(Seq[Seq[.]]
或其他)中找到实际的整数索引。
但是我找不到获得这种 f(key: K): Int
功能的方法。
我可以使用 Map[K,Int]
而不是 SortedSet[K]
,其中的值是索引,但我发现这太过分了(而且打字不好)。
有什么想法吗?
编辑
Map 方法类似于,但在 2D 中:
val myKeys = // SortedSet("A", "B", "C")
val data = // Array(13,42,117)
val keyIndices = myKeys.zipWithIndex.toMap
// get indices of "B", and lookup in data array
data(keyIndices("B"))
我为 Map 解决方案写了 "not well typed" 因为类型不保证索引是连续的并且从 0 开始。而有序序列中的位置是。
选择的解决方案
我选择了 because it was best for my actual problem. But and 个答案更适合标题。
使用 zipWithIndex
应该可以:
def getIndex[T](xs: scala.collection.SortedSet[T], x:T): Option[Int] =
xs.zipWithIndex.find(_._1 == x).map(_._2)
val a = scala.collection.SortedSet("a", "l", "m", "o", "n", "d")
getIndex(a, "a") // => Some(0)
getIndex(a, "m") // => Some(3)
getIndex(a, "x") // => None
您可以创建隐式 class 以将功能添加到 SortedSet
implicit class SortedListFunctions[T](val s: SortedSet[T]){
def getIndex(key: T): Int = {
val notDropped = s.dropWhile(_ != key).size
if(notDropped == 0) -1
else s.size - notDropped
}
}
使用隐式 class 如果它存在于 API
中,您可以调用 getIndex(..) a
set.getIndex(key)
请注意,这可能不是搜索已排序内容的非常有效的方法。
如果你的 SortedSet 真的很大,你可以考虑 Binary Searching 它
简答
保持Set
你不能。有办法通过索引获取元素是 Seq
.
的特征
scala> val data =scala.collection.SortedSet("a", "l", "m", "o", "n", "d")
data: scala.collection.SortedSet[String] = TreeSet(a, d, l, m, n, o)
scala> data(1)
<console>:12: error: type mismatch;
found : Int(1)
required: String
data(1)
^
scala> data("a")
res3: Boolean = true
在这个例子中,apply 方法检查给定的参数是否包含在集合中。
我会采用您已经使用 Map
建议的方法。或者将数据转换为 Seq
scala> val indexedData = data.toVector
indexedData: Vector[String] = Vector(a, d, l, m, n, o)
scala> indexedData(2)
res9: String = l
scala> indexedData.indexOf("l")
res1: Int = 2
我正在实施某种 "record matrix",其中轴索引是某种类型 K
(例如字符串)的(唯一)键。这些键不需要排序,但我需要一个顺序,所以我选择了一个 SortedSet。
键 (SortedSet) 的主要目的是在底层二维数据数组(Seq[Seq[.]]
或其他)中找到实际的整数索引。
但是我找不到获得这种 f(key: K): Int
功能的方法。
我可以使用 Map[K,Int]
而不是 SortedSet[K]
,其中的值是索引,但我发现这太过分了(而且打字不好)。
有什么想法吗?
编辑
Map 方法类似于,但在 2D 中:
val myKeys = // SortedSet("A", "B", "C")
val data = // Array(13,42,117)
val keyIndices = myKeys.zipWithIndex.toMap
// get indices of "B", and lookup in data array
data(keyIndices("B"))
我为 Map 解决方案写了 "not well typed" 因为类型不保证索引是连续的并且从 0 开始。而有序序列中的位置是。
选择的解决方案
我选择了
使用 zipWithIndex
应该可以:
def getIndex[T](xs: scala.collection.SortedSet[T], x:T): Option[Int] =
xs.zipWithIndex.find(_._1 == x).map(_._2)
val a = scala.collection.SortedSet("a", "l", "m", "o", "n", "d")
getIndex(a, "a") // => Some(0)
getIndex(a, "m") // => Some(3)
getIndex(a, "x") // => None
您可以创建隐式 class 以将功能添加到 SortedSet
implicit class SortedListFunctions[T](val s: SortedSet[T]){
def getIndex(key: T): Int = {
val notDropped = s.dropWhile(_ != key).size
if(notDropped == 0) -1
else s.size - notDropped
}
}
使用隐式 class 如果它存在于 API
中,您可以调用 getIndex(..) a set.getIndex(key)
请注意,这可能不是搜索已排序内容的非常有效的方法。 如果你的 SortedSet 真的很大,你可以考虑 Binary Searching 它
简答
保持Set
你不能。有办法通过索引获取元素是 Seq
.
scala> val data =scala.collection.SortedSet("a", "l", "m", "o", "n", "d")
data: scala.collection.SortedSet[String] = TreeSet(a, d, l, m, n, o)
scala> data(1)
<console>:12: error: type mismatch;
found : Int(1)
required: String
data(1)
^
scala> data("a")
res3: Boolean = true
在这个例子中,apply 方法检查给定的参数是否包含在集合中。
我会采用您已经使用 Map
建议的方法。或者将数据转换为 Seq
scala> val indexedData = data.toVector
indexedData: Vector[String] = Vector(a, d, l, m, n, o)
scala> indexedData(2)
res9: String = l
scala> indexedData.indexOf("l")
res1: Int = 2