Удалить элемент в списке, если рядом - PullRequest
1 голос
/ 11 марта 2020

У меня есть список типа Fruit.
Я ищу удалить пары APPLE, BANANA, только если они соседние и в этом порядке.

Например:

val basket: Fruitbasket = List(PEAR, APPLE, BANANA, CHERRY)

Сокращено до:

LIST(PEAR, CHERRY)

Другой пример:

val basket2: Fruitbasket = List(PEAR, APPLE, PEAR, BANANA, CHERRY)

Не будет уменьшено и останется как:

List(PEAR, APPLE, PEAR, BANANA, CHERRY)

Я понимаю, что архивирование хвостом - это способ сравнения соседних элементов, но как лучше всего отфильтровать и разархивировать?

basket.zip(basket.tail)

Ответы [ 3 ]

3 голосов
/ 11 марта 2020

Полагаю, вы могли бы просто использовать хвостовую рекурсивную функцию и сопоставление с образцом:

import scala.annotation.tailrec

def filterOut(basket: List[String]): List[String] = {

    @tailrec
    def go(basket: List[String], acc: List[String] = Nil): List[String] = {

      basket match {
        case "APPLE" :: "BANANA" :: xs => go(xs, acc)
        case x :: xs => go(xs, x :: acc)
        case Nil => acc.reverse
      }
    }

    go(basket)
}


filterOut(List("PEAR", "APPLE", "BANANA", "CHERRY"))  // List("PEAR", "CHERRY")
filterOut(List("PEAR", "APPLE", "PEAR", "BANANA", "CHERRY")) // List("PEAR", "APPLE", "PEAR", "BANANA", "CHERRY")
1 голос
/ 11 марта 2020

Вероятно, вам следует использовать indexOfSlice метод. Вот моя реализация:

def censoreSeq0[T](col: Seq[T], censored:Seq[T]):Seq[T] = if (censored.isEmpty) col else {
  col.indexOfSlice(censored) match {
    case -1 => col
    case x => col.take(x) ++ censoreSeq0(col.drop(x+censored.length), censored)
  }
}

В этой скрипте есть больше реализаций, которые делают это немного по-другому: https://scalafiddle.io/sf/EgQ7FCT/3

0 голосов
/ 13 марта 2020

Если вы уверены, что это своего рода служебный метод, вы можете изменить список подстрочных элементов для повышения производительности. Пример украденного у Кшиштофа Атласика ответа.

import scala.annotation.tailrec
import scala.collection.mutable.ListBuffer

def filterOut(basket: List[String]): List[String] = {
  @tailrec
  def go(basket: List[String], acc: ListBuffer[String] = new ListBuffer[String]): ListBuffer[String] = {
    basket match {
      case Nil => acc
      case "APPLE" :: "BANANA" :: xs => go(xs, acc)
      case x :: xs => go(xs, acc += x)
    }
  }

  go(basket).result()
}


filterOut(List("PEAR", "APPLE", "BANANA", "CHERRY"))  // List("PEAR", "CHERRY")
filterOut(List("PEAR", "APPLE", "PEAR", "BANANA", "CHERRY")) // List("PEAR", "APPLE", "PEAR", "BANANA", "CHERRY")
...