前一段时间,有同事问Erlang中如何实现将一个列表中元素打乱,我第一反应就是每次根据列表长度随机出一个下标,将该元素剔出列表,加入到新列表中,重复上面步骤至原列表为空便可。没过多久一个同事说,直接给每一个元素一个随机值,而后排序一下就能够了。其实游戏中常常会遇到这种须要打乱顺序的状况,例如洗牌,网上搜寻了一番,发现了些作法。java
参考 http://erlangdisplay.iteye.com/blog/380774 中的算法
版本1(速度快,随机化很差):数组
shuffle_v1(L) -> List1 = [{random:uniform(), X} || X <- L], List2 = lists:keysort(1, List1), [E || {_, E} <- List2].
上面的版本2 代码很多,是叫Fisher-Yates shuffle算法,根据http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle中描述,跟我开始想的方法差很少,但原算法涉及到数组的元素交换,我我的感受erlang的list在这方面不太方便,果真有更加简洁的方案,dom
http://en.literateprograms.org/Fisher-Yates_shuffle_(Erlang) code
shuffle(List) -> shuffle(List, []). shuffle([], Acc) -> Acc; shuffle(List, Acc) -> {Leading, [H | T]} = lists:split(random:uniform(length(List)) - 1, List), shuffle(Leading ++ T, [H | Acc]).
固然原算法进行数组的元素交换,只须要一个临时变量便可完成随机数组的生成,特别当数组长度很大的状况下,能节省很多内存。orm