2009-10-08 43 views

回答

14

这样做是使用一个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) 
+9

现在过于复杂*。斯卡拉2.7没有更好的东西。 – 2011-07-13 14:00:22

9

如果你指的是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) 

对于Seq,根据ticket 929,该方法应该在Scala2.8中可用。
在此期间,您需要定义一个特设的静态方法为one seen here

+0

如果我有Seq [String]而不是List? – 2009-10-08 15:46:59

+0

调用'toList',显然是:)或者,如@Synesso提议的那样,使用'foldLeft'。 – incarnate 2011-10-24 13:22:23

2

一个简单的ad-hoc方法只是添加到列表中的设置,并使用从那里:

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(或任何可迭代),但这并不是必需在2.8,其中removeDuplicates方法将可能是更具有可读性。此外,不确定运行时性能与更深思熟虑的转换。

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

10

推出自己的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) 
+3

我非常喜欢这个,因为它允许复杂的过滤逻辑。谢谢! – incarnate 2011-10-24 13:20:32

178

在2.8,它是:

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

Imho,1和2不是列表中的唯一项目。只有3个。您从列表中创建唯一项目列表,这是不同的事情。 – 2012-05-11 20:02:33

+13

如果这就是你想要的(通常不是),请使用: List(1,2,3,2,1).groupBy(x => x).filter(_._ 2.lengthCompare(1)== 0).keySet – moveaway00 2013-07-03 15:56:47

6

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

如何在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)) 

会找到它。

+3

大多数java/scala开发人员会将“给定列表中的唯一项目”的问题翻译为“给定列表中的所有不同值”而不是“在给定列表中单独显示的所有值”......这是你的每个答案如何解释它,以及提问的人(谁批准了这样的答案)。 2年后会出现什么情况,并且在解析已经回答的问题时特别敏感? – mujimu 2012-07-02 20:04:44

+1

@mujimu:我不记得为什么2年后我偶然发现了这个问题。也许sombebody关闭了一个类似的问题,确切的重复并链接到这里。在寻找其他人的解决方案之前,我经常尝试为自己回答这些问题作为练习;他们是否有类似或更好的解决方案,或者是否合理发布我的作品。所以我发现其他人回答了另一个问题。在了解其他人如何理解这个问题后,我仍然认为这个术语是错误的。一个句子的含义不应该由多数人来判断。 – 2012-07-03 10:13:05

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

list。toSet将这样做,因为Set按定义只包含唯一元素

+0

5年前,在之前的回答中指出了这一点,你的观点是什么? – jwvh 2017-02-20 05:28:35