Фильтрация списка путем удаления ненужных значений в Scala - PullRequest
0 голосов
/ 23 октября 2018

Будучи новичком в Scala, я наткнулся на проблему, которую не могу решить.По сути, мне дают координаты из файла, который мне удалось добавить в список, а затем отсортировать все эти значения в разные списки, как показано ниже:

List(List(61, 62, 63, 64, 65, 66, 67), List(21, 23, 25, 26, 27))

Используя этот код:

val lines = io.Source.fromFile("in.txt").getLines

val coordinates =
  lines
    .drop(0)
    .toList
    .sortWith(_<_)
    .mkString
    .replaceAll("\\s", "")
    .grouped(2)
    .toList

val conditions = 1 to 5000

val que = coordinates.map(_.toInt)

val thisIsIt = conditions.foldLeft(List():List[List[Int]])((acc, elem) =>
  que
    .filter(_.toString.startsWith(elem.toString))::acc)
    .filterNot(_.isEmpty)
    .filter(_.length > 3)
    .map(_.toList)

Что мне нужно сделать, это найти координаты в каждом списке, которые будут следовать той же схеме.Например, в списке

List(21, 23, 25, 26, 27) 

я хотел бы удалить элемент «26», поскольку разница между соседними значениями должна быть «2».

23-21 = 2
25-23 = 2
26-25 = 1, 

Но если мыпроверив разницу между следующим элементом после 26 и предыдущим элементом 25, мы увидим, что:

27-25 = 2

Таким образом, если 26 удалено, условие, что разница между каждым смежным значением должна быть "2"становится истинным, давая нам список

List(21, 23, 25, 27)

Другой список, который:

List(61, 62, 63, 64, 65, 66, 67) 

должен просто возвращать тот же список, потому что разница между элементами постоянна, и это "1".

В конце мне нужно вернуть список

List(List(61, 62, 63, 64, 65, 66, 67), List(21, 23, 25, 27))

Я приведу еще один пример со списком

List(31, 32, 33, 36, 37)

Хотя разница между первым3 элемента - это действительно «1», и то же самое можно сказать о разнице между последними 2 элементами, невозможно пройти от начала списка до его конца с постоянной разницей между значениями.

Theкоординаты могут измениться, и число значений в каждом списке также может измениться.Буду признателен за любую помощь, так как я мертв в моих следах.Я пытался использовать функции, которые используют head и tail , перебирая список и применяя условия, но на самом деле ничего не работает.

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Звучит так, что, возможно, вы просто хотите уменьшить каждый List[Int] до тех элементов (если они есть), которые находятся на одинаковом расстоянии, начиная с конца и заканчивая включительно.

Вот мое мнение.

val input = List(List(61, 62, 63, 64, 65, 66, 67)
               , List(31, 32, 33, 36, 37)
               , List(21, 23, 25, 26, 27)
               , List(2, 12, 19, 22, 36))

val result = input.map{ lst =>
  val hd = lst.head
  val end = lst.last
  val distance = end - hd
  Stream.from(1).take(distance/2).flatMap{ step =>
    val rng = hd to end by step
    if (distance%step == 0 && rng.diff(lst).isEmpty)
      Some(rng.toList)
    else None
  }.headOption.getOrElse(Nil)
}
//result: List[List[Int]] = List(List(61, 62, 63, 64, 65, 66, 67)
//                             , List()
//                             , List(21, 23, 25, 27)
//                             , List(2, 19, 36))

Примечание. Предполагается, что каждый List[Int] заказан, или, по крайней мере, .last больше .head.

0 голосов
/ 23 октября 2018

Я до сих пор не знаю, понимаю ли я, что вы пытаетесь сделать.Вот что я думаю вы могли бы иметь в виду: найти самый длинный возможный подсписок из данного списка, содержащий не менее трех элементов исходного списка, включая первый и последний, такой, чтобы расстояние между каждым последующимЭлемент является постоянным.

В этом случае, здесь простое решение.По сути, сначала вы обнаруживаете все возможные расстояния (вычитая из каждого элемента заголовок списка и сохраняя положительные значения, но не превышающие половины расстояния между заголовком и списком списка), а затем пытаетесьпостроить результирующий подсписок для каждого из этих расстояний.

  def findIt(list: List[Int]) = {
    @tailrec def doIt(
      list: List[Int],
      candidates: List[Int],
      last: Int 
    ): Option[List[Int]] = candidates match {
       case Nil => None
       case dist :: rest => 
         val result = list.foldLeft[List[Int]](Nil) {
           case (Nil, x) => List(x)
           case (l@(head :: _), x) if x == head + dist => x :: l
           case (l, _) => l
         }
         if(result.head == last) Some(result.reverse) 
         else doIt(list, rest, last)
    }

    val candidates = list.foldLeft[List[Int]](Nil) { 
       case (Nil, x) => List(0)
       case (l, x) => (x - list.head) :: l
    }
    if(list.nonEmpty) doIt(
     list, 
     candidates.filter(x => x > 0 && x <= candidates.head/2).reverse, 
     list.head + candidates.head
    ) else None
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...