Scala: обновить неизменяемую коллекцию несколько раз и вернуть ее - PullRequest
0 голосов
/ 04 марта 2020

Я новичок ie в Scala и немного застрял с неизменяемыми коллекциями из-за моего Java фона.

Давайте представим, что у нас есть неизменный 2D-вектор N * N

val field: Vector[Vector[Boolean]] =
    Vector(
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false),
      Vector(false,false,false,false,false,false,false,false,false,false)
    )

У нас также есть список кортежей (Int, Int)

val coordinatesToUpdate: List[(Int, Int)] = List((0,0), (2,4), (6,7), (4,4))

Мне нужно обновить свой вектор, изменив все значения в векторе для координат с coordinatesToUpdate от false до true.

Таким образом, результатом должен быть новый Вектор, содержащий ИСТИНА в связанных координатах:

Vector(
          Vector(true,false,false,false,false,false,false,false,false,false),
          Vector(false,false,false,false,false,false,false,false,false,false),
          Vector(false,false,false,false,true,false,false,false,false,false),
          Vector(false,false,false,false,false,false,false,false,false,false),
          Vector(false,false,false,false,true,false,false,false,false,false),
          Vector(false,false,false,false,false,false,false,false,false,false),
          Vector(false,false,false,false,false,false,false,true,false,false),
          Vector(false,false,false,false,false,false,false,false,false,false),
          Vector(false,false,false,false,false,false,false,false,false,false),
          Vector(false,false,false,false,false,false,false,false,false,false)
        )

Я могу обновить свою коллекцию с одной точкой ...

def markPointInField(field: Vector[Vector[Boolean]])(point: (Int, Int)): Vector[Vector[Boolean]] = {
    field.updated(point._1, field(point._1).updated(point._2, true))
  }

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

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

Я знаю, что работает с неизменными коллекциями вы всегда создаете новую из старой. Технически, я могу создать N новых Векторов для своих обновлений N:

val firstUpdate: Vector[Vector[Boolean]] = markPointInField(field)(coordinatesToUpdate.head)
val secondUpdate: Vector[Vector[Boolean]] = markPointInField(firstUpdate)(coordinatesToUpdate(1))
val thirdUpdate: Vector[Vector[Boolean]] = markPointInField(secondUpdate)(coordinatesToUpdate(2))
.........

Конечно, у нас может быть много проблем с этой реализацией (например, если у нас будет 500 очков) ), но по крайней мере здесь я понимаю , как я передаю обновленное состояние Vector между выполнениями update-fuction . Я каждый раз создаю новую переменную и сохраняю в ней состояние моего вектора. В первой переменной я сохраняю состояние моего вектора после пометки 1 точки на поле. Затем я передаю его функции update-fuction и сохраняю состояние с 2 точками во 2-й переменной и т. Д. c.

. Именно в этот момент я не могу понять, как реализовать с функциональной парадигмой (т.е. без 500-строчный код с созданием 500 новых векторов).

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

1 Ответ

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

Возможно, комбинация map, zipWithIndex и contains могла бы сделать это

field.zipWithIndex.map { case (row, idx) =>
  row.zipWithIndex.map { case (column, jdx) =>
    if (coordinatesToUpdate.contains(idx -> jdx)) true else column
  }
}

Вероятно, хорошая идея для сравнения производительности с jmh.

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