No Scala, como removo duplicatas de uma lista?


94

Suponha que eu tenha

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

Existe uma operação de lista que retorna "a", "b", "c"

Respostas:


175

Dê uma olhada no ScalaDoc for Seq ,

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

Atualize . Outros sugeriram usar em Setvez de List. Tudo bem, mas esteja ciente de que, por padrão, a Setinterface não preserva a ordem dos elementos. Você pode querer usar uma implementação de Set que preserva explicitamente a ordem, como collection.mutable.LinkedHashSet .


2
E se você tiver uma lista de arquivos e precisar comparar algo como parte do nome do arquivo?
ozônio

4
@ozone Pergunta interessante. Talvez a maneira mais fácil seja criar um novo mapa de tipo Map[String, File], onde as chaves são a parte do nome do arquivo de interesse. Assim que o mapa for construído, você pode chamar o valuesmétodo para obter um Iterabledos valores - as chaves serão todas distintas por construção.
Kipton Barros

@KiptonBarros e eu acho que você pode fazer isso usando o groupBymembro de scala.collection.Iterable[A].
Louis-Jacob Lebel

18

scala.collection.immutable.Listagora tem um .distinctmétodo.

Portanto, dirty.distinctagora é possível fazer chamadas sem converter para um Setou Seq.


1
.distinctnão está definido para scala.collection.Iterable[A]. Então, nesse caso, você teria que usar upgrade dirtypara a Seqou a de Setqualquer maneira (ou seja, usando um .toList, .toSeqou .toSetmembros) para que isso funcione.
Louis-Jacob Lebel

15

Antes de usar a solução do Kitpon, pense em usar um Setao invés de um List, isso garante que cada elemento seja único.

Como a maioria das operações de lista ( foreach, map, filter, ...) são os mesmos para os conjuntos e listas, mudando coleção poderia ser muito fácil no código.


7

Usar Set em primeiro lugar é a maneira certa de fazer isso, é claro, mas:

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

Trabalho. Ou apenas toSetporque suporta oSeq Traversable interface.


1
Editei sua resposta porque Setimplementa Traversable, não Seq. A diferença é que Seqgarante uma ordem aos elementos, enquanto Traversablenão.
Kipton Barros

-3

inArr.distinct foreach println _


isso imprime a saída desejada, o OP não estava pedindo para devolvê-la (como uma lista, presumivelmente)?
RobP

-4

A maneira algorítmica ...

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
Ele tem uma lista, não uma string. Isso não responde à pergunta.
Tim Gautier
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.