In Scala come rimuovo i duplicati da un elenco?


94

Supponiamo di averlo fatto

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

Esiste un'operazione di elenco che restituisce "a", "b", "c"

Risposte:


175

Dai un'occhiata a ScalaDoc per Seq ,

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

Aggiorna . Altri hanno suggerito di utilizzare Setpiuttosto che List. Va bene, ma tieni presente che per impostazione predefinita l' Setinterfaccia non mantiene l'ordine degli elementi. Si consiglia di utilizzare un set di implementazione che esplicitamente non conserva ordine, come collection.mutable.LinkedHashSet .


2
Cosa succede se hai un elenco di file e devi confrontare qualcosa come una parte del nome del file?
ozono

4
@ ozono Domanda interessante. Forse il modo più semplice è creare una nuova mappa di tipo Map[String, File], in cui le chiavi sono la parte del nome del file di interesse. Una volta costruita la mappa, puoi chiamare il valuesmetodo per ottenere un Iterabledi valori: le chiavi saranno tutte distinte per costruzione.
Kipton Barros

@KiptonBarros e penso che tu possa farlo usando il groupBymembro di scala.collection.Iterable[A].
Louis-Jacob Lebel

18

scala.collection.immutable.Listora ha un .distinctmetodo.

Quindi dirty.distinctora è possibile chiamare senza convertire in Seto Seq.


1
.distinctnon è definito per scala.collection.Iterable[A]. Quindi, in questo caso, dovreste usare l'aggiornamento dirtya una Seqo Setcomunque (cioè utilizzando uno .toList, .toSeqo .toSetmembri) per questo al lavoro.
Louis-Jacob Lebel

15

Prima di utilizzare la soluzione di Kitpon, pensa di utilizzare a Setpiuttosto che a List, in modo che ogni elemento sia unico.

Come la maggior parte delle operazioni di lista ( foreach, map, filter, ...) sono gli stessi per i set e liste, cambiando la raccolta potrebbe essere molto semplice nel codice.


7

Usare Set in primo luogo è il modo giusto per farlo, ovviamente, ma:

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

Lavori. O proprio toSetcome supporta ilSeq Traversable interfaccia.


1
Ho modificato la tua risposta perché Setimplementa Traversable, no Seq. La differenza è che Seqgarantisce un ordine agli elementi, mentre Traversableno.
Kipton Barros

-3

inArr.distinct foreach println _


questo stampa l'output desiderato, non era OP chiedendo di restituirlo (come un elenco, presumibilmente)?
Rapina

-4

Il modo algoritmico ...

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

1
Ha una lista, non una stringa. Questo non risponde alla domanda.
Tim Gautier
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.