Wie man in Scala einzigartige Gegenstände in der Liste findet


Antworten:


24

Die effizienteste Methode zur Aufrechterhaltung der Ordnung wäre die Verwendung einer Setals zusätzliche Datenstruktur:

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)
}

Wir können dies mit einer impliziten Konvertierung in eine schönere Syntax einschließen:

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
Es ist jetzt überkompliziert . Scala 2.7 hatte nichts Besseres.
Daniel Spiewak

211

In 2.8 ist es:

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

1
Imho, 1 und 2 sind keine eindeutigen Elemente in der Liste. Nur die 3 ist. Sie erstellen eine Liste eindeutiger Elemente aus der Liste, was etwas anderes ist.
Benutzer unbekannt

18
Wenn Sie dies möchten (normalerweise nicht), gehen Sie zu: List (1,2,3,2,1) .groupBy (x => x) .filter (_._ 2.lengthCompare (1) == 0). keySet
moveaway00

13

Rollen Sie Ihren eigenen Uniq-Filter mit Auftragserhaltung:

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
Ich habe diesen sehr genossen, da er eine komplexe Filterlogik ermöglicht. Vielen Dank!
BorisOkunskiy

10

Wenn Sie sich auf den Rosetta-Code beziehen : Erstellen Sie eine Folge eindeutiger Elemente

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)

Da Listes unveränderlich ist, werden Sie die Initiale nicht Listdurch Aufrufen ändernremoveDuplicates

Warnung: Wie in diesem Tweet (!) Erwähnt , bleibt die Reihenfolge nicht erhalten:

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)

Für a Seqsollte diese Methode in Scala2.8 gemäß Ticket 929 verfügbar sein .
In der Zwischenzeit müssen Sie eine statische Ad-hoc-Methode wie die hier gezeigte definieren


Was soll ich tun, wenn Seq [String] nicht List ist?
Volodymyr Bezuglyy

Rufen Sie toListanscheinend an :) Oder verwenden Sie, wie von @Synesso vorgeschlagen foldLeft.
BorisOkunskiy

7

Imho, alle Interpretationen der Frage sind falsch:

Wie finde ich in Scala einzigartige Gegenstände in der Liste?

Angesichts dieser Liste:

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

Das einzige eindeutige Element in der Liste ist 2. Die anderen Elemente sind nicht eindeutig.

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

werde es finden.


4
Die meisten Java / Scala-Entwickler würden eine Frage von "eindeutigen Elementen in einer bestimmten Liste" als "alle unterschiedlichen Werte mit einer bestimmten Liste" übersetzen, nicht als "alle Werte, die einzeln in einer bestimmten Liste angezeigt werden" ... so lautet jede Antwort vor Ihrer interpretierte es ebenso wie die Person, die die Frage stellte (die eine solche Antwort genehmigte). Was bringt es, 2+ Jahre später zu kommen und besonders sensibel auf das Parsen einer bereits beantworteten Frage zu reagieren?
Mujimu

1
@mujimu: Ich erinnere mich nicht, warum ich 2 Jahre später über die Frage gestolpert bin. Vielleicht hat jemand eine ähnliche Frage als genaues Duplikat geschlossen und hier verlinkt. Oft versuche ich, solche Fragen als Übung für mich selbst zu beantworten, bevor ich nach Lösungen anderer suche. ob sie eine ähnliche oder eine bessere Lösung haben oder ob es sinnvoll ist, meine zu veröffentlichen. Also stellte ich fest, dass die anderen eine andere Frage beantworteten. Nachdem ich weiß, wie andere die Frage anders verstanden haben, denke ich immer noch, dass die Terminologie falsch ist. Die Bedeutung eines Satzes sollte nicht mit der Mehrheit beurteilt werden.
Benutzer unbekannt

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

2

Eine einfache Ad-hoc-Methode besteht darin, die Liste einem Set hinzuzufügen und von dort aus Folgendes zu verwenden:

  val l = List(1,2,3,3,3,4,5,5,6,7,8,8,8,9,9)
  val s = Set() ++ x
  println(s)

Produziert:

> Set(5, 1, 6, 9, 2, 7, 3, 8, 4)

Dies funktioniert für eine Seq (oder eine beliebige Iterable), ist jedoch in 2.8 nicht erforderlich, wo die removeDuplicates-Methode wahrscheinlich besser lesbar ist. Ich bin mir auch nicht sicher über die Laufzeitleistung im Vergleich zu einer durchdachten Konvertierung.

Beachten Sie auch die verlorene Bestellung.


0

list.toSet wird dies tun, da Set per Definition nur eindeutige Elemente enthält


1
In einer früheren Antwort vor über 5 Jahren wurde darauf hingewiesen: Was ist Ihr Punkt?
Jwvh
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.