Резюме: Я написал очень эффективную функцию, которая возвращает List.distinct
и List
, состоящие из каждого элемента, который появился более одного раза, и индекса, в котором появился дубликат элемента.
Примечание. Этот ответ представляет собой прямую копию ответа на связанный вопрос .
Подробности: Если вам нужна дополнительная информация оСами же дубликаты, как и я, я написал более общую функцию, которая перебирает List
(поскольку порядок был значительным) ровно один раз и возвращает Tuple2
, состоящий из дедуплированного исходного List
(все дубликаты после первогоудален, т. е. аналогично вызову distinct
) и второй List
, показывающей каждый дубликат и индекс Int
, при котором он произошел в исходном List
.
Вот функция:
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
Это прямая копия функции filterDupes
из моей библиотеки Scala с открытым исходным кодом, ScalaOlio .Он расположен на org.scalaolio.collection.immutable.List_._
.