Repeating a List in Scala
I am a Scala noob. I have decided to write a spider solitaire solver as a first exercise to learn the language and functional programming in general.
I would like to generate a randomly shuffled deck of cards containing 1, 2, or 4 suits. Here is what I came up with:
val numberOfSuits = 1
(List("clubs", "diamonds", "hearts", "spades").take(numberOfSuits) * 4).take(4)
which should return
List("clubs", "clubs", "clubs", "clubs")
List("clubs", "diamonds", "clubs", "diamonds")
List("clubs", "diamonds", 开发者_如何学C"hearts", "spades")
depending on the value of numberOfSuits, except there is no List "multiply" operation that I can find. Did I miss it? Is there a better way to generate the complete deck before shuffling?
BTW, I plan on using an Enumeration for the suits, but it was easier to type my question with strings. I will take the List generated above and using a for comprehension, iterate over the suits and a similar List of card "ranks" to generate a complete deck.
Flatten a finite lists of lists:
scala> List.fill(2)(List(1, 2, 3, 4)).flatten
res18: List[Int] = List(1, 2, 3, 4, 1, 2, 3, 4)
Flatten an infinite Stream of lists, take the first N elements:
scala> Stream.continually(List(1, 2, 3, 4)).flatten.take(8).toList
res19: List[Int] = List(1, 2, 3, 4, 1, 2, 3, 4)
You should look up the scaladoc for the object List
. It has all manners of interesting methods for creation of lists. For instance, the following does exactly what you were trying to:
List.flatten(List.make(4, List("clubs", "diamonds", "hearts", "spades").take(numberOfSuits))).take(4)
A much nicer code, however, would be this (Scala 2.7):
val suits = List("clubs", "diamonds", "hearts", "spades")
List.tabulate(4, i => suits.apply(i % numberOfSuits))
On Scala 2.8 tabulate
is curried, so the correct syntax would be:
List.tabulate(4)(i => suits.apply(i % numberOfSuits))
You can expand a numeric sequence and flatMap
instead of multiplying.
scala> (1 to 3).flatMap(_=>List(1,2,3,4).take(2)).take(4)
res1: Seq[Int] = List(1, 2, 1, 2)
This works in 2.7.x also.
Edit: since you're less experienced with Scala, you may not yet have come across the enrich-my-library pattern. If you want to multiply your lists a lot, you can add a custom conversion class:
class MultipliableList[T](l: List[T]) {
def *(n: Int) = (1 to n).flatMap(_=>l).toList
}
implicit def list2multipliable[T](l: List[T]) = new MultipliableList[T](l)
and now you can
scala> List(1,2,3)*4
res2: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)
(Generally, to reuse such implicits, declare them in an object and then import MyObject._ to get the implicit conversion and corresponding class in scope.)
If you use cats
library, you can make use of Semigroup
's method combineN
. It repeates a list N
times.
import cats.implicits._
import cats.syntax.semigroup._
scala> List("clubs", "diamonds", "hearts", "spades").combineN(2)
res1: List[String] = List(clubs, diamonds, hearts, spades, clubs, diamonds, hearts, spades)
精彩评论