【发布时间】:2011-03-09 12:23:13
【问题描述】:
这是一个非常令人不快的惊喜:
scala> Set(1, 2, 3, 4, 5)
res18: scala.collection.immutable.Set[Int] = Set(4, 5, 1, 2, 3)
scala> Set(1, 2, 3, 4, 5).toList
res25: List[Int] = List(5, 1, 2, 3, 4)
这个例子本身对我的问题提出了一个“否”的答案。那么ListSet呢?
scala> import scala.collection.immutable.ListSet
scala> ListSet(1, 2, 3, 4, 5)
res21: scala.collection.immutable.ListSet[Int] = Set(1, 2, 3, 4, 5)
这似乎有效,但我应该依赖这种行为吗? 还有哪些其他数据结构适用于唯一项的不可变集合,其中必须保留原始顺序?
顺便说一句,我确实知道List 中的distict 方法。问题是,我想在界面级别强制项目的唯一性(同时保留顺序),所以使用 distinct 会弄乱我的整洁设计..
编辑
ListSet 似乎也不太可靠:
scala> ListSet(1, 2, 3, 4, 5).toList
res28: List[Int] = List(5, 4, 3, 2, 1)
EDIT2
在寻找完美设计时,我尝试了这个:
scala> class MyList[A](list: List[A]) { val values = list.distinct }
scala> implicit def toMyList[A](l: List[A]) = new MyList(l)
scala> implicit def fromMyList[A](l: MyList[A]) = l.values
实际可行:
scala> val l1: MyList[Int] = List(1, 2, 3)
scala> l1.values
res0: List[Int] = List(1, 2, 3)
scala> val l2: List[Int] = new MyList(List(1, 2, 3))
l2: List[Int] = List(1, 2, 3)
然而,问题是我不想在库之外公开MyList。有没有办法在覆盖时进行隐式转换?例如:
trait T { def l: MyList[_] }
object O extends T { val l: MyList[_] = List(1, 2, 3) }
scala> O.l mkString(" ") // Let's test the implicit conversion
res7: String = 1 2 3
我想这样做:
object O extends T { val l = List(1, 2, 3) } // Doesn't work
【问题讨论】:
-
在哪里可以阅读比“Scala 编程”和 Scaladocs 更深入的有关 scala 集合的信息?
-
这是开始学习 Scala 集合的好地方:scala-lang.org/docu/files/collections-api/collections.html
-
集合按(数学)定义没有顺序,大多数语言都遵循该约定。好奇,你为什么希望他们有?除了唯一性之外,顺序是
Seq和Set之间唯一的实质性区别! -
在这种情况下,我不太关心我的数据结构的数学属性。我只需要保留原始顺序的不同项目的不可变集合。称它为列表、集合、向量、表格或“卡车负载”:)