免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 11155 | 回复: 29

洗牌的技巧  关闭 [复制链接]

论坛徽章:
0
发表于 2006-07-31 10:53 |显示全部楼层
参看:

如何用shell实现“洗牌”效果?
文本文件随机取几万行怎么取?





  1.                                       洗牌的技巧







  2.     洗牌问题:

  3.     洗一副扑克,有什么好办法?既能洗得均匀,又能洗得快?即相对于一个文件来说怎样
  4. 高效率的实现乱序排列?

  5.     关于洗牌问题,其实已经有了一个很好的shell解法,这里另外给三个基于AWK的方法,
  6. 有错误之处还请不吝指出。



  7. 方法一穷举:
  8.     类似于穷举法,构造一个散列来记录已经打印行出现行的次数,如果出现次数多于一
  9. 次则不进行处理,这样可以防止重复,但缺点是加大了系统的开销。



  10. awk -v N=`sed -n '$=' data` '
  11. BEGIN{
  12. FS="\n";
  13. RS=""
  14. }
  15. {
  16. srand();
  17. while(t!=N){
  18.   x=int(N*rand()+1);
  19.   a[x]++;
  20.   if(a[x]==1)
  21.     {
  22.         print $x;t++
  23.     }
  24.   }
  25. }
  26. ' data


  27. 方法二变换:
  28.     基于数组下标变换的办法,即用数组储存每行的内容,通过数组下标的变换
  29. 交换数组的内容,效率好于方法一。


  30. #! /usr/awk

  31. BEGIN{
  32. srand();
  33. }


  34. {
  35. b[NR]=$0;
  36. }


  37. END{

  38. C(b,NR);
  39. for(x in b)
  40.   {
  41.     print b[x];
  42.   }

  43. }


  44. function C(arr,len,i,j,t,x){

  45. for(x in arr)
  46.   {
  47.       i=int(len*rand())+1;
  48.       j=int(len*rand())+1;
  49.       t=arr[i];
  50.       arr[i]=arr[j];
  51.       arr[j]=t;
  52.   }

  53. }




  54. 方法三散列:

  55.     三个方法中最好的。
  56.     利用AWK中散列的特性(详细请看:info gawk 中的7.x ),只要构造一个
  57. 随机不重复的散列函数即可,因为一个文件每行的linenumber是独一无二的,所
  58. 以用:

  59.     随机数+每行linenumber    ------对应------>    那一行的内容

  60. 即为所构造的随机函数。
  61.     从而有:


  62.     awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data







  63.     其实大家担心的使用内存过大的问题不必太在意,可以做一个测试:

  64. 测试环境:
  65. PM 1.4GHz CPU,40G硬盘,内存256M的LAPTOP
  66. SUSE 9.3  GNU bash version 3.00.16 GNU Awk 3.1.4

  67. 产生一个五十几万行的随机文件,大约有38M:

  68. od /dev/urandom |dd  count=75000 >data



  69. 拿效率较低的方法一来说:

  70. 洗牌一次所用时间:

  71. time awk -v N=`sed -n '$=' data` '
  72. BEGIN{
  73. FS="\n";
  74. RS=""
  75. }
  76. {
  77. srand();
  78. while(t!=N){
  79.   x=int(N*rand()+1);
  80.   a[x]++;
  81.   if(a[x]==1)
  82.     {
  83.         print $x;t++
  84.     }
  85.   }
  86. }
  87. ' data

  88. 结果(文件内容省略):


  89. real    3m41.864s
  90. user    0m34.224s
  91. sys     0m2.102s


  92. 所以效率还是勉强可以接受的。

  93. 方法二的测试:

  94. time awk -f awkfile datafile

  95. 结果(文件内容省略):

  96. real    2m26.487s
  97. user    0m7.044s
  98. sys     0m1.371s

  99. 效率明显好于第一个。


  100. 接着考察一下方法三的效率:

  101. time awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data

  102. 结果(文件内容省略):

  103. real    0m49.195s
  104. user    0m5.318s
  105. sys     0m1.301s


  106. 对于一个38M的文件来说已经相当不错了。
  107. 玩的愉快!
复制代码

评分

参与人数 1可用积分 +3 收起 理由
r2007 + 3 精品文章

查看全部评分

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
发表于 2006-07-31 10:55 |显示全部楼层
楼主莫非是dbcat的马甲?

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
发表于 2006-07-31 10:57 |显示全部楼层
dbcat是楼主的马甲

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
发表于 2006-07-31 10:58 |显示全部楼层
原帖由 waker 于 2006-7-31 10:57 发表
dbcat是楼主的马甲

很像很像,dbcatMM很久没露面了,~

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
发表于 2006-07-31 11:02 |显示全部楼层
随机不重复的散列函数即可,因为一个文件每行的linenumber是独一无二的,所
以用:

    随机数+每行linenumber    ------对应------>    那一行的内容

即为所构造的随机函数。

b[rand()NR]
机率非常小,但不能排除重复可能
用 b[rand()" "NR]如何?

论坛徽章:
7
荣誉版主
日期:2011-11-23 16:44:17子鼠
日期:2014-07-24 15:38:07狮子座
日期:2014-07-24 11:00:54巨蟹座
日期:2014-07-21 19:03:10双子座
日期:2014-05-22 12:00:09卯兔
日期:2014-05-08 19:43:17卯兔
日期:2014-08-22 13:39:09
发表于 2006-07-31 11:07 |显示全部楼层
原帖由 waker 于 2006-7-31 11:02 发表
随机不重复的散列函数即可,因为一个文件每行的linenumber是独一无二的,所
以用:

    随机数+每行linenumber    ------对应------>    那一行的内容

即为所构造的随机函数。

b[rand()NR]
机率非 ...

同楼上观点一样
也可用逗号b[rand(),NR],默认是\034字符
散列的思路真棒,赞!

论坛徽章:
0
发表于 2006-07-31 11:10 |显示全部楼层
原帖由 waker 于 2006-7-31 11:02 发表
随机不重复的散列函数即可,因为一个文件每行的linenumber是独一无二的,所
以用:

    随机数+每行linenumber    ------对应------>    那一行的内容

即为所构造的随机函数。

b[rand()NR]
机率非 ...


问世间此山是否最高?天若有情天亦老,爱你爱到忘不了

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
发表于 2006-07-31 11:23 |显示全部楼层
原帖由 苏蓉蓉 于 2006-7-31 11:10 发表


问世间此山是否最高?天若有情天亦老,爱你爱到忘不了

晕~,waker好福气~  

论坛徽章:
7
荣誉版主
日期:2011-11-23 16:44:17子鼠
日期:2014-07-24 15:38:07狮子座
日期:2014-07-24 11:00:54巨蟹座
日期:2014-07-21 19:03:10双子座
日期:2014-05-22 12:00:09卯兔
日期:2014-05-08 19:43:17卯兔
日期:2014-08-22 13:39:09
发表于 2006-07-31 11:30 |显示全部楼层
原帖由 寂寞烈火 于 2006-7-31 11:23 发表

晕~,waker好福气~  


曾子曰:机率非常小,但不能排除重复可能
我就是那个重复的
强烈申请和waker同等待遇

论坛徽章:
0
发表于 2006-07-31 13:41 |显示全部楼层
干嘛呢? 干嘛呢~
打情骂翘啊?  
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP