Создание повторяющегося списка true / false в scala - PullRequest
1 голос
/ 03 февраля 2012

Я хочу сгенерировать Seq / List значений true / false, которые можно заархивировать с помощью некоторого ввода, чтобы выполнить эквивалент проверки того, является ли индекс цикла for нечетным / четным.

Есть лилучше, чем

input.zip((1 to n).map(_ % 2 == 0))

или

input.zip(List.tabulate(n)(_ % 2 != 0))

Я бы подумал, что-то вроде (true, false).repeat(n/2) более очевидно

Ответы [ 6 ]

9 голосов
/ 03 февраля 2012

Использование @ идеи ДэйвГрифита :

input.zip(Stream.iterate(false)(!_))

Или, если вы используете этот шаблон в нескольких местах:

def falseTrueStream = Stream.iterate(false)(!_)

input.zip(falseTrueStream)

Это имеет явное преимущество ненеобходимо указать размер списка ложных истин.

Редактировать:

Конечно, def falseTrueStream создает поток true / false объекты каждый раз, когда вы его используете, и как @ DanielCSobral упоминает , делая его val будет удерживать объекты в памяти (пока программа не завершится)если val находится на object).

Если вы слегка злой и хотите преждевременно оптимизировать его, вы можете построить Stream объекты самостоятельно.

object TrueFalseStream extends Stream[Boolean] {
  val tailDefined = true

  override val isEmpty = false

  override val head = true

  override val tail = FalseTrueStream
}

object FalseTrueStream extends Stream[Boolean] {
  val tailDefined = true

  override val isEmpty = false

  override val head = false

  override val tail = TrueFalseStream
}
4 голосов
/ 04 февраля 2012

В Haskell есть очень полезная функция - cycle, которая полезна для таких целей:

haskell> zip [1..7] $ cycle [True, False]
[(1,True),(2,False),(3,True),(4,False),(5,True),(6,False),(7,True)]

По какой-то причине в стандартной библиотеке Scala его нет. Вы можете определить его самостоятельно, а затем использовать его.

scala> def cycle[A](s: Stream[A]): Stream[A] = Stream.continually(s).flatten
cycle: [A](s: Stream[A])Stream[A]

scala> (1 to 7) zip cycle(Stream(true, false))
res13: scala.collection.immutable.IndexedSeq[(Int, Boolean)] = Vector((1,true), (2,false), (3,true), (4,false), (5,true), (6,false), (7,true))
4 голосов
/ 03 февраля 2012

Если вы хотите список чередующихся true / false размером n:

List.iterate(false, n)(!_)

Итак, вы можете сделать:

val input = List("a", "b", "c", "d")
input.zip(List.iterate(false, input.length)(!_))
//List[(java.lang.String, Boolean)] = List((a,false), (b,true), (c,false), (d,true))
2 голосов
/ 04 февраля 2012

Вы хотите

input.indices.map(_%2==0)
1 голос
/ 03 февраля 2012

Я не мог придумать ничего более простого (и это далеко не просто):

(for(_ <- 1 to n/2) yield List(true, false)).flatten

и:

(1 to n/2).foldLeft(List[Boolean]()) {(cur,_) => List(true, false) ++ cur}

Наблюдайте за странным n!

Однако, исходя из ваших требований, выглядит, что вы, возможно, захотите что-то ленивый :

def oddEven(init: Boolean): Stream[Boolean] = Stream.cons(init, oddEven(!init))

... и это никогда не заканчивается (попробуйте: oddEven(true) foreach println).Теперь вы можете взять столько, сколько хотите:

oddEven(true).take(10).toList
0 голосов
/ 03 февраля 2012

... для того, чтобы эквивалентно проверить, является ли индекс цикла нечетным / четным.

Я игнорирую ваш конкретный запрос и решаю вашу главную проблему впо-другому.Вы можете сделать свою собственную функцию управления, например, так:

def for2[A,B](xs: List[A])(f: A => Unit, g: A => Unit): Unit = xs match {
    case (y :: ys) => {
      f(y)
      for2(ys)(g, f)
    }
    case _ => Unit
}

Тестирование

> for2(List(0,1,2,3,4,5))((x) => println("E: " + x), (x) => println("O: " + x))
E: 0
O: 1
E: 2
O: 3
E: 4
O: 5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...