假设我试图在f#中实现某种扑克计划。首先是这种类型系统的正确使用,这里有大量的新手。
type Suit =
| Hearts
| Diamonds
| Spades
| Clubs
type Card = {
Suit:Suit
Rank:int
}
type Hand = {
Cards:List<Card>
}
无论如何,假设我想要一个函数来返回一个可能的持卡的随机列表。我想有两个函数可以链接在一起,但是我很难实现它们而不会产生大量的对象。列表模块中的每个函数都将返回一个新列表,而let关键字无法更改引用的值。那么实现这一目标的功能方式是什么。到目前为止我有这个
let generateCards = {
let ranks = [ 1..52 ]...
}
let shuffle cards = {
}
let cards = shuffle generateCards
答案 0 :(得分:4)
一种改组牌组的方法是用一系列随机数字拉链,然后按这些数字排序,然后再解压缩。
let allCards =
[ for rank in 2..14 do
for suit in [Hearts; Diamonds; Spades; Clubs] do
yield { Suit = suit; Rank = rank } ]
let shuffle cards =
let rnd = System.Random()
let rndSequence = Seq.initInfinite (fun _ -> rnd.Next())
Seq.zip cards rndSequence |> Seq.sortBy snd |> Seq.map fst |> Seq.toList
shuffle allCards
上面的内容也可以简化(对@ DaveShaw的评论点头),但是以人们不太明显为代价,通过随机生成的密钥对序列进行排序:
let shuffle cards =
let rnd = System.Random()
cards |> List.sortBy (fun _ -> rnd.Next())
甚至更简单(但可能会产生更多性能影响):
let shuffle cards = List.sortBy (fun _ -> System.Guid.NewGuid()) cards
为了极致简洁,请采用无点风格:
let shuffle = List.sortBy (fun _ -> System.Guid.NewGuid())