总结:
我编写了一个非常高效的函数,它返回 List.distinct 和 List ,其中包含多次出现的每个元素以及出现重复元素的索引。
注意:这个答案是straight copy of the answer on a related question。
详情:
如果您需要更多关于重复项本身的信息,就像我所做的那样,我已经编写了一个更通用的函数,它只迭代一次 List(因为排序很重要)并返回一个由原始 @987654327 组成的 Tuple2 @deduped(删除第一个之后的所有重复项;即与调用distinct 相同)和第二个List 显示每个重复项以及它在原始List 中出现的Int 索引。
函数如下:
def filterDupes[A](items: List[A]): (List[A], List[(A, Int)]) = {
def recursive(remaining: List[A], index: Int, accumulator: (List[A], List[(A, Int)])): (List[A], List[(A, Int)]) =
if (remaining.isEmpty)
accumulator
else
recursive(
remaining.tail
, index + 1
, if (accumulator._1.contains(remaining.head))
(accumulator._1, (remaining.head, index) :: accumulator._2)
else
(remaining.head :: accumulator._1, accumulator._2)
)
val (distinct, dupes) = recursive(items, 0, (Nil, Nil))
(distinct.reverse, dupes.reverse)
}
下面是一个示例,它可能会使其更直观。鉴于此字符串值列表:
val withDupes =
List("a.b", "a.c", "b.a", "b.b", "a.c", "c.a", "a.c", "d.b", "a.b")
...然后执行以下操作:
val (deduped, dupeAndIndexs) =
filterDupes(withDupes)
...结果是:
deduped: List[String] = List(a.b, a.c, b.a, b.b, c.a, d.b)
dupeAndIndexs: List[(String, Int)] = List((a.c,4), (a.c,6), (a.b,8))
如果您只想要重复项,您只需 map 穿过 dupeAndIndexes 并调用 distinct:
val dupesOnly =
dupeAndIndexs.map(_._1).distinct
...或全部在一次调用中:
val dupesOnly =
filterDupes(withDupes)._2.map(_._1).distinct
...或者如果首选Set,请跳过distinct 并调用toSet...
val dupesOnly2 =
dupeAndIndexs.map(_._1).toSet
...或全部在一次调用中:
val dupesOnly2 =
filterDupes(withDupes)._2.map(_._1).toSet
这是我的开源 Scala 库 ScalaOlio 中的 filterDupes 函数的直接副本。它位于org.scalaolio.collection.immutable.List_._。