【发布时间】:2009-10-08 15:37:38
【问题描述】:
如何在 Scala 中查找 List 中的唯一项?
【问题讨论】:
标签: scala
如何在 Scala 中查找 List 中的唯一项?
【问题讨论】:
标签: scala
在 2.8 中,它是:
List(1,2,3,2,1).distinct // => List(1, 2, 3)
【讨论】:
最有效的保单方式是使用Set作为辅助数据结构:
def unique[A](ls: List[A]) = {
def loop(set: Set[A], ls: List[A]): List[A] = ls match {
case hd :: tail if set contains hd => loop(set, tail)
case hd :: tail => hd :: loop(set + hd, tail)
case Nil => Nil
}
loop(Set(), ls)
}
我们可以使用隐式转换将其包装成更好的语法:
implicit def listToSyntax[A](ls: List[A]) = new {
def unique = unique(ls)
}
List(1, 1, 2, 3, 4, 5, 4).unique // => List(1, 2, 3, 4, 5)
【讨论】:
滚动您自己的具有订单保留功能的 uniq 过滤器:
scala> val l = List(1,2,3,3,4,6,5,6)
l: List[Int] = List(1, 2, 3, 3, 4, 6, 5, 6)
scala> l.foldLeft(Nil: List[Int]) {(acc, next) => if (acc contains next) acc else next :: acc }.reverse
res0: List[Int] = List(1, 2, 3, 4, 6, 5)
【讨论】:
如果您参考Rosetta Code: Create a Sequence of unique elements
val list = List(1,2,3,4,2,3,4,99)
val l2 = list.removeDuplicates
// l2: scala.List[scala.Int] = List(1,2,3,4,99)
由于List 是不可变的,因此您不会通过调用removeDuplicates 来修改初始的List
警告:正如this tweet(!) 所述,这不会保留顺序:
scala> val list = List(2,1,2,4,2,9,3)
list: List[Int] = List(2, 1, 2, 4, 2, 9, 3)
scala> val l2 = list.removeDuplicates
l2: List[Int] = List(1, 4, 2, 9, 3)
根据ticket 929,对于Seq,该方法应该在Scala2.8 中可用。
同时,您需要定义一个 ad-hoc 静态方法为 one seen here
【讨论】:
toList :) 或者,如@Synesso 所建议,使用foldLeft。
恕我直言,问题的所有解释都是错误的:
如何在 Scala 中查找 List 中的唯一项?
鉴于此列表:
val ili = List (1, 2, 3, 4, 4, 3, 1, 1, 4, 1)
列表中唯一唯一的项目是2。其他项目不是唯一的。
ili.toSet.filter (i => ili.indexOf (i) == ili.lastIndexOf (i))
会找到的。
【讨论】:
list.filter { x => list.count(_ == x) == 1 }
【讨论】:
一个简单的临时方法就是将列表添加到一个集合中,然后从那里使用:
val l = List(1,2,3,3,3,4,5,5,6,7,8,8,8,9,9)
val s = Set() ++ x
println(s)
生产:
> Set(5, 1, 6, 9, 2, 7, 3, 8, 4)
这适用于 Seq(或任何 Iterable),但在 2.8 中不是必需的,其中 removeDuplicates 方法可能更具可读性。此外,不确定运行时性能与更深思熟虑的转换。
另外,请注意丢失的订单。
【讨论】:
list.toSet 会这样做,因为根据定义,Set 只包含唯一元素
【讨论】: