Wie entferne ich in Scala Duplikate aus einer Liste?

94

Angenommen, ich habe

val dirty = List("a", "b", "a", "c")

Gibt es eine Listenoperation, die "a", "b", "c" zurückgibt?

deltanovember
quelle

Antworten:

175

Schauen Sie sich das ScalaDoc für Seq an ,

scala> dirty.distinct
res0: List[java.lang.String] = List(a, b, c)

Update . Andere haben vorgeschlagen, Seteher als zu verwenden List. Das ist in Ordnung, aber beachten Sie, dass die SetSchnittstelle standardmäßig die Elementreihenfolge nicht beibehält. Möglicherweise möchten Sie eine Set-Implementierung verwenden, die die Reihenfolge explizit beibehält , z. B. collection.mutable.LinkedHashSet .

Kipton Barros
quelle
2
Was ist, wenn Sie eine Liste von Dateien haben und einen Teil des Dateinamens vergleichen müssen?
Ozon
4
@ozone Interessante Frage. Vielleicht ist der einfachste Weg , um eine neue erstellen Karten des Typs Map[String, File], in dem der Schlüssel der Teil des Dateinamen von Interesse ist. Sobald die Karte erstellt wurde, können Sie die valuesMethode aufrufen , um einen Iterableder Werte abzurufen. Die Schlüssel unterscheiden sich alle durch die Konstruktion.
Kipton Barros
@KiptonBarros und ich denke, Sie können dies tun, indem Sie das groupByMitglied von verwenden scala.collection.Iterable[A].
Louis-Jacob Lebel
18

scala.collection.immutable.Listhat jetzt eine .distinctMethode.

Das Aufrufen dirty.distinctist jetzt möglich, ohne in ein Setoder zu konvertieren Seq.

Crockpotveggies
quelle
1
.distinctist nicht definiert für scala.collection.Iterable[A]. In diesem Fall müssten Sie also ein Upgrade dirtyauf a Seqoder a Setverwenden (dh entweder .toListmit .toSeqoder mit .toSetMitgliedern), damit dies funktioniert.
Louis-Jacob Lebel
15

Denken Sie vor der Verwendung der Kitpon-Lösung an die Verwendung von a Setanstelle von a List, um sicherzustellen, dass jedes Element einzigartig ist.

Da die meisten Listenoperationen ( foreach, map, filter, ...) sind für Sets und Listen, könnte sehr leicht in der Codesammlung zu ändern sein.

paradigmatisch
quelle
7

Die Verwendung von Set ist natürlich der richtige Weg, aber:

scala> List("a", "b", "a", "c").toSet.toList
res1: List[java.lang.String] = List(a, b, c)

Funktioniert. Oder genauso toSetwie es das unterstütztSeq Traversable Schnittstelle.

Zentrop
quelle
1
Ich habe Ihre Antwort bearbeitet, weil Setimplementiert Traversable, nicht Seq. Der Unterschied besteht darin, dass Seqden Elementen eine Reihenfolge garantiert wird, während Traversabledies nicht der Fall ist.
Kipton Barros
-3

inArr.distinct foreach println _

Sumit Pal
quelle
Dadurch wird die gewünschte Ausgabe gedruckt. Hat OP nicht darum gebeten, sie zurückzugeben (vermutlich als Liste)?
RobP
-4

Der algorithmische Weg ...

def dedupe(str: String): String = {
  val words = { str split " " }.toList

  val unique = words.foldLeft[List[String]] (Nil) {
    (l, s) => {
      val test = l find { _.toLowerCase == s.toLowerCase } 
      if (test == None) s :: l else l
    }
  }.reverse

  unique mkString " "
}
Farquad
quelle
1
Er hat eine Liste, keine Zeichenfolge. Dies beantwortet die Frage nicht.
Tim Gautier