Как в Scala найти уникальные предметы в Списке - PullRequest
76 голосов
/ 08 октября 2009

Как в Scala найти уникальные предметы в Списке?

Ответы [ 8 ]

202 голосов
/ 22 июля 2010

В 2.8 это:

List(1,2,3,2,1).distinct  // => List(1, 2, 3)
22 голосов
/ 09 октября 2009

Наиболее эффективный способ сделать это с сохранением порядка - использовать Set в качестве структуры вспомогательных данных:

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

Мы можем заключить это в более приятный синтаксис, используя неявное преобразование:

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)
12 голосов
/ 09 октября 2009

Сверните свой собственный фильтр uniq с сохранением заказа:

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)
10 голосов
/ 08 октября 2009

Если вы ссылаетесь на код Розетты: создайте последовательность уникальных элементов

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)

Поскольку List является неизменным, вы не измените исходное значение List, вызвав removeDuplicates

Предупреждение: как отмечено в этом твите (!), Это не сохраняет порядок:

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)

Для Seq этот метод должен быть доступен в Scala2.8, в соответствии с билетом 929 .
В то же время вам необходимо определить специальный статический метод как , который можно увидеть здесь

6 голосов
/ 19 февраля 2012

Имхо, все толкования вопроса неверны:

Как в Scala найти уникальные предметы в Списке?

Учитывая этот список:

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

единственный уникальный элемент в списке - 2. Другие предметы не являются уникальными.

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

найдет его.

4 голосов
/ 30 июня 2015
list.filter { x => list.count(_ == x) == 1 }
2 голосов
/ 08 октября 2009

Простой специальный метод - просто добавить список в набор и использовать оттуда:

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

Производит:

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

Это работает для Seq (или любого Iterable), но не обязательно в 2.8, где метод removeDuplicates, вероятно, будет более читабельным. Кроме того, вы не уверены в производительности во время выполнения и более продуманном преобразовании.

Также обратите внимание на потерянный заказ.

0 голосов
/ 20 февраля 2017

list.toSet сделает это, так как набор по определению содержит только уникальные элементы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...