2009-10-08 24 views

Respuesta

14

La forma orden de preservación más eficaz de hacer esto sería utilizar un Set como una estructura de datos auxiliares:

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

Nosotros Puede envolver esto en una sintaxis más agradable utilizando una conversión implícita:

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) 
+9

Es demasiado complicado * ahora *. Scala 2.7 no tenía nada mejor. –

9

Si se refiere a la Rosetta Code: Create a Sequence of unique elements

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) 

Desde List es inmutable, usted no modifica la inicial List llamando removeDuplicates

Advertencia: (!) Como se ha mencionado por this tweet, esto no conserva el orden:

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) 

Para un Seq, ese método debería estar disponible en Scala2.8, de acuerdo con ticket 929.
Mientras tanto, tendrá que definir un método estático ad-hoc como el one seen here

+0

¿Qué debo hacer si tengo Seq [String] not List? –

+0

Llamar a 'toList', al parecer :) O, como lo propone @Synesso, use' foldLeft'. – incarnate

2

Un método ad-hoc simple es sólo para añadir la lista a un conjunto, y utilizar desde allí:

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

Produce:

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

Esto funciona para un Seq (o cualquier Iterable), pero no es necesario en 2.8, en donde el método RemoveDuplicates probablemente será más fácil de leer. Además, no estoy seguro sobre el rendimiento del tiempo de ejecución frente a una conversión más pensada.

Además, tenga en cuenta la pérdida de pedidos.

10

rollo su propio filtro uniq con la retención de orden:

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) 
+3

Realmente disfruté mucho de esto, ya que permite una compleja lógica de filtrado. ¡Gracias! – incarnate

178

En 2.8, que es:

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

Imho, 1 y 2 no son elementos únicos en la lista. Solo el 3 es. Usted crea una lista de elementos únicos de la lista, que es algo diferente. –

+13

Si eso es lo que quiere (generalmente no lo es), vaya con: Lista (1,2,3,2,1) .grupoBy (x => x) .filter (_._ 2.lengthCompare (1) == 0) .keySet – moveaway00

6

En mi humilde opinión, todas las interpretaciones de la cuestión son falsas:

¿Cómo en Scala para encontrar artículos únicos en la lista?

Dada esta lista:

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

el único elemento único en la lista es 2. Los otros artículos no son únicos.

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

lo encontrará.

+3

la mayoría de los desarrolladores java/scala traducirían una pregunta de "artículos únicos en una lista dada" como "todos los valores distintos con una lista dada" no "todos los valores aparecen singularmente dentro de una lista dada" ... que es cómo cada respuesta antes de la tuya lo interpretó, así como también la persona que hizo la pregunta (quién aprobó dicha respuesta). ¿Qué viene en más de 2 años más tarde y ser más sensible en el análisis de una pregunta ya respondida? – mujimu

+1

@mujimu: No recuerdo por qué me tropecé con la pregunta 2 años después. Tal vez sombebody cerró una pregunta similar como duplicado exacto y se vinculó aquí. A menudo trato de responder estas preguntas por mí mismo como un ejercicio antes de buscar las soluciones de los demás; si tienen una solución similar o mejor o si tiene sentido publicar la mía. Entonces descubrí que los demás respondieron una pregunta diferente. Después de saber cómo otros entendieron la pregunta de manera diferente, todavía creo que la terminología es incorrecta. El significado de una oración no debe juzgarse por mayoría. –

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

lista.toSet lo hará ya que Set por definición solo contiene elementos únicos

+0

Esto fue señalado, en una respuesta anterior, hace más de 5 años, ¿cuál es su punto? – jwvh

Cuestiones relacionadas