Scala: удалить повторяющиеся целые числа из вектора (кортежи (Int, Int), ...) - PullRequest
0 голосов
/ 06 мая 2020

У меня большой размер вектора (около 2000 элементов), внутри он состоит из множества кортежей, Tuple(Int,Int), т.е.

val myVectorEG = Vector((65,61), (29,49), (4,57), (12,49), (24,98), (21,52), (81,86), (91,23), (73,34), (97,41),...))

I wi sh, чтобы удалить повторяющиеся / дублированные целые числа для каждый кортеж с индексом (0), i.e. if Tuple(65,xx) repeated at other Tuple(65, yy) inside the vector, it should be removed)

Я разрешаю получить к ним доступ и распечатать этим методом:

val (id1,id2) = ( allSource.foreach(i=>println(i._1)),  allSource.foreach(i=>i._2))

Как я могу удалить повторяющиеся целые числа? Или мне следует использовать другой метод вместо использования foreach для доступа к моему индексу элемента в 0

Ответы [ 4 ]

3 голосов
/ 06 мая 2020

Чтобы удалить все дубликаты, сначала сгруппируйте по первому кортежу и соберите только те кортежи, где есть только один кортеж, принадлежащий этому конкретному ключу (_._1). Затем сгладьте результат.

myVectorEG.groupBy(_._1).collect{
  case (k, v) if v.size == 1 => v
}.flatten

Это возвращает List, который вы можете вызвать .toVector, если вам нужен Vector

3 голосов
/ 06 мая 2020

Это выполняет свою работу и сохраняет порядок (в отличие от других решений), но O(n^2) поэтому потенциально медленный для 2000 элементов:

myVectorEG.filter(x => myVectorEG.count(_._1 == x._1) == 1)

Это более эффективно для больших векторов, но все же сохраняет порядок:

val keep =
  myVectorEG.groupBy(_._1).collect{
    case (k, v) if v.size == 1 => k
  }.toSet

myVectorEG.filter(x => keep.contains(x._1))
2 голосов
/ 06 мая 2020

Вы можете использовать отдельныйBy для удаления дубликатов.

В случае Vector[(Int, Int)] это будет выглядеть так

myVectorEG.distinctBy(_._1)

Обновлено, если вам нужно удалить все дубликаты:

Вы можете использовать groupBy но это изменит ваш порядок.

myVectorEG.groupBy(_._1).filter(_._2.size == 1).flatMap(_._2).toVector
1 голос
/ 06 мая 2020

Другой вариант, используя то, что вы хотите, чтобы список был отсортирован в конце.

def sortAndRemoveDuplicatesByFirst[A : Ordering, B](input: List[(A, B)]): List[(A, B)] = {
  import Ordering.Implicits._

  val sorted = input.sortBy(_._1)

  @annotation.tailrec
  def loop(remaining: List[(A, B)], previous: (A, B), repeated: Boolean, acc: List[(A, B)]): List[(A, B)] =
    remaining match {
      case x :: xs =>
        if (x._1 == previous._1)
          loop(remaining = xs, previous, repeated = true, acc)
        else if (!repeated)
          loop(remaining = xs, previous = x, repeated = false, previous :: acc)
        else
          loop(remaining = xs, previous = x, repeated = false, acc)

      case Nil =>
        (previous :: acc).reverse
    }

  sorted match {
    case x :: xs =>
      loop(remaining = xs, previous = x, repeated = false, acc = List.empty)

    case Nil =>
      List.empty
  }
}

Что вы можете протестировать следующим образом:

val data = List(
  1 -> "A",
  3 -> "B",
  1 -> "C",
  4 -> "D",
  3 -> "E",
  5 -> "F",
  1 -> "G",
  0 -> "H"
)

sortAndRemoveDuplicatesByFirst(data)
// res: List[(Int, String)] = List((0,H), (4,D), (5,F))

(я использовал Список вместо Vector , чтобы упростить и повысить производительность для написания алгоритма tail-re c)

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