如何在Scala中查找列表中的唯一项


Answers:


24

这样做最有效的顺序保留方法是将aSet用作辅助数据结构:

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)

14
现在它太复杂。Scala 2.7没有任何更好的选择。
Daniel Spiewak 2011年

211

在2.8中,它是:

List(1,2,3,2,1).distinct  // => List(1, 2, 3)

1
恕我直言,1和2不是列表中的唯一项。只有3是。您从列表创建唯一项列表,这是另一回事。
用户未知

18
如果那是您想要的(通常不是),请使用:List(1,2,3,2,1).groupBy(x => x).filter(_._ 2.lengthCompare(1)== 0)。 keySet
moveaway00 2013年

13

滚动保留订单的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)

4
实际上,我非常喜欢它,因为它允许复杂的过滤逻辑。谢谢!
BorisOkunskiy 2011年

10

如果您引用Rosetta代码:创建一个唯一元素序列

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是不可变的,因此您不会List通过调用removeDuplicates

警告:如此推文(!)所述,这不会保留顺序:

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)

对于Seq,根据票证929,该方法应该在Scala2.8中可用。
同时,您需要定义一种临时静态方法,如下 所示


如果我有Seq [String] not List该怎么办?
Volodymyr Bezuglyy,2009年

toList显然是打电话给:),或者按照@Synesso的建议,使用foldLeft
BorisOkunskiy 2011年

7

恕我直言,这个问题的所有解释都是错误的:

如何在Scala中找到列表中的唯一项?

鉴于此列表:

val ili = List (1, 2, 3, 4, 4, 3, 1, 1, 4, 1) 

列表中唯一的唯一项是2。其他项目不是唯一的。

ili.toSet.filter (i => ili.indexOf (i) == ili.lastIndexOf (i))

会找到它。


4
大多数Java / scala开发人员会将“给定列表中的唯一项”转换为“给定列表中的所有不同值”而不是“所有值在给定列表中单独显示”的问题...这就是您面前的每个答案的方式解释它,以及询问问题的人(谁批准了这样的答案)。超过2年后会出现什么,并且对已经回答的问题的解析更加敏感,这会增加什么?
mujimu'7

1
@mujimu:我不记得为什么两年后我偶然发现了这个问题。也许sombebody关闭了一个类似的问题,即确切重复并在此处链接。在寻找别人的解决方案之前,我经常会尝试自己为自己回答这些问题。他们有类似的解决方案还是更好的解决方案,或者发布我的发布是否有意义。因此,我发现其他人回答了一个不同的问题。在了解了其他人对问题的理解后,我仍然认为该术语是错误的。句子的含义不应以多数来判断。
用户未知

4
list.filter { x => list.count(_ == x) == 1 }

2

一种简单的临时方法是将列表添加到集合,然后从那里使用:

  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方法可能更易读。另外,不确定运行时性能还是经过深思熟虑的转换。

另外,请注意丢失的顺序。


0

list.toSet将执行此操作,因为按定义设置仅包含唯一元素


1
在5年前的先前答案中指出了这一点,您的意思是什么?
jwvh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.