Board logo

标题: 【练习-052】根据原始数据进行相关统计操作 [打印本页]

作者: batman    时间: 2009-11-19 11:49     标题: 【练习-052】根据原始数据进行相关统计操作

出题目的:
    综合考察会员的文本数据处理能力
加分原则:
    满分30分,酌情加分,以思路为重
题目如下:
    有一从excel(实际中是要对excel直接操作)导入的文本a.txt如下:
  1. 部门 A项完成 B项完成 C项完成 D项完成 E项完成 F项完成 当天排名 当月累计排名
  2. 一分局 2 7 0 1 7 7 2  1
  3. 二分局 0 0 0 1 0 0 6  2
  4. 三分局 2 8 1 1 1 9 1  3
  5. 四分局 0 0 0 1 1 0 5  5
  6. 五分局 0 0 0 1 2 1 3  7
  7. 六分局 0 0 0 1 0 0 4  6
  8. 七分局 0 5 0 1 0 6 6  3
复制代码
要求对用批处理后生成统计文本b.txt,要求列出每项完成的总和,如有完成为0的局则
一一列出,没有则列出"无";将当日排名和当月排名按名次从小到大的顺序列出局名和名次
,请注意有排名相同的情况。
  1. A项完成4,完成为0的局:二分局,四分局,五分局,六分局,七分局
  2. B项完成20,完成为0的局:二分局,四分局,五分局,六分局
  3. C项完成1,完成为0的局:一分局,二分局,四分局,五分局,六分局,七分局
  4. D项完成7,完成为0的局:无
  5. E项完成11,完成为0的局:二分局,六分局,七分局
  6. F项完成23,完成为0的局:二分局,四分局,六分局
  7. 当日排名:三分局1,一分局2,五分局3,六分局4,四分局5,二分局6,七分局6
  8. 当月累计排名:一分局1,二分局2,三分局3,七分局3,四分局5,六分局6,五分局7
复制代码
   提示:分局数和项目数都是未知的

[ 本帖最后由 batman 于 2009-11-19 21:34 编辑 ]
作者: batman    时间: 2009-11-19 15:00

提示:批可以不用读取a.txt第一行,用一系列的变量来代替首行内容
作者: 523066680    时间: 2009-11-19 17:11

……打算看帖不答题……
作者: netbenton    时间: 2009-11-19 20:17

呵呵。。。
我也是这么想的 ^_^
作者: zqz0012005    时间: 2009-11-19 21:19

其实是两个不同的问题,而其中排序问题没必要放在这里,可以另外出题(好像出过?)
作者: batman    时间: 2009-11-19 21:22     标题: 回复 5楼 的帖子

这个排序真是不同于以往的排序,原因是你就是排出了名次的序,你还要考虑和分局关联,特别是出现同名次的情况下
作者: zqz0012005    时间: 2009-11-19 21:31

还是一样啊,只是把字符交换一下位置而已。
一分局 2 7 0 1 7 7 2  1
二分局 0 0 0 1 0 0 6  2

一分局 1
二分局 2

1一分局
2二分局

排好再交换回来
作者: batman    时间: 2009-11-19 21:39     标题: 回复 7楼 的帖子

楼上是不是搞错题意了,排名是用一定的公式算出来的,而不是由前面的完成情况来定的。。。
作者: zqz0012005    时间: 2009-11-19 21:40

“导入的文本a.txt如下”

后面两列数据是怎么来的?要根据什么公式?还是自己编算法?

[ 本帖最后由 zqz0012005 于 2009-11-19 21:43 编辑 ]
作者: batman    时间: 2009-11-19 21:43

直接读到的啊,排名肯定是有同名次的情况出现的,如当日排名:三分局1,一分局2,五分局3,六分局4,四分局5,二分局6,七分局6
作者: zqz0012005    时间: 2009-11-19 21:51

既然是直接读到的,那可能你没有明白我7楼的意思
::截取两列:
一分局 1
二分局 2
三分局 3
四分局 5
五分局 7
六分局 6
七分局 3

::交换:
...
作者: zqz0012005    时间: 2009-11-19 21:55

即使列数未确定,也很容易求得。
即使不求列数,只截取特定两列也容易。
作者: zqz0012005    时间: 2009-11-19 21:57

这个排序问题其实也不错:
以A3列的大小为主要排序,A2列的大小为次要排序,应该怎么实现?
http://bbs.verybat.org/viewthread.php?tid=17101
作者: batman    时间: 2009-11-19 21:57     标题: 回复 12楼 的帖子

我没说此题无解吧,晕,我只是一再在强调出现同名次的情况需要处理
作者: zqz0012005    时间: 2009-11-19 22:03     标题: 回复 14楼 的帖子

晕,我也没说此题无解,12楼只是对11楼的补充,同时都是对7楼的解释。

而且题目给的结果并未处理啊:
当月累计排名:一分局1,二分局2,三分局3,七分局3,四分局5,六分局6,五分局7
两个第三名后,直接是第五名,没有将名次序号调成4
作者: batman    时间: 2009-11-19 22:07     标题: 回复 15楼 的帖子

为什么要调成第四名,说了有并列名次出现的情况。。。

[ 本帖最后由 batman 于 2009-11-19 22:10 编辑 ]
作者: zqz0012005    时间: 2009-11-19 22:11     标题: 回复 16楼 的帖子

交换位置后:
0001 一分局
0002 二分局
0003 三分局
0005 四分局
0007 五分局
0006 六分局
0003 七分局
......
0123 一百五十分局

(前面的0是添加的,再截取后4位)
既然无需调整名次序号,那不就结了,直接sort

[ 本帖最后由 zqz0012005 于 2009-11-19 22:13 编辑 ]
作者: batman    时间: 2009-11-19 22:13     标题: 回复 17楼 的帖子

还请就此题给出完整代码
作者: zqz0012005    时间: 2009-11-19 23:26

达到要求的输出格式使得步骤多了点。
(显然,Ctrl+A可见)
  1. @echo off
  2. %1 %2
  3. setlocal enableDelayedExpansion
  4. set n=0
  5. for /f "tokens=1* delims==" %%a in ('"set /p head=<1.txt& set head"') do ^
  6. for %%i in (%%b) do set _!n!=%%i& set /a n+=1
  7. set /a items=n-3, day_ranking=n-1, month_ranking=n
  8. for /f "skip=1 delims=" %%a in (1.txt) do set m=0&for %%i in (%%a) do (
  9.     if "!m!"=="0" set department=%%i
  10.     for %%x in (_!m!) do (
  11.         if "%%i"=="0" set %%x_0=!%%x_0! !department!
  12.         set /a !%%x! += %%i
  13.     )
  14.     set /a m+=1
  15.     set serial=0000%%i& set serial=!serial:~-4!
  16.     if !m!==!day_ranking! set _day_ranking=!_day_ranking! !serial!.!department!
  17.     if !m!==!month_ranking! set _month_ranking=!_month_ranking! !serial!.!department!
  18. )
  19. for /l %%a in (1 1 %items%) do (
  20.     if "!_%%a_0!"=="" set _%%a_0= 无
  21.     set #%%a=!_%%a! ^^!!_%%a!^^!, 完成为0的局:!_%%a_0!
  22. )
  23. for /f "tokens=1* delims==" %%a in ('set #') do echo %%b
  24. for /f "tokens=* delims=0" %%a in ('%~s0 goto sort_ "!_day_ranking!"^|sort') do set #day_ranking=!#day_ranking!,%%~xa%%~na
  25. for /f "tokens=* delims=0" %%a in ('%~s0 goto sort_ "!_month_ranking!"^|sort') do set #month_ranking=!#month_ranking!,%%~xa%%~na
  26. set #day_ranking=!#day_ranking:~1!
  27. set #month_ranking=!#month_ranking:~1!
  28. echo 当日排名: !#day_ranking:.=!
  29. echo 当月累计排名: !#month_ranking:.=!
  30. pause&exit/b
  31. :sort_
  32. for /f "delims=" %%a in ("%~3") do for %%i in (%%~a) do echo %%i
  33. goto :eof
复制代码


[ 本帖最后由 batman 于 2009-11-21 11:58 编辑 ]
作者: batman    时间: 2009-11-19 23:41

楼上的效率显然有问题。。。这就是用^|sort造成的

[ 本帖最后由 batman 于 2009-11-19 23:50 编辑 ]
作者: zqz0012005    时间: 2009-11-20 00:05

前面数据整理不怎么耗时,主要是不想用临时文件而将排序模块整合在一起造成的。
如果不担心分局数和项目数加起来会超过变量最大长度,两次排序其实可以goto一次完成,将_day_ranking和_month_ranking分别不同的前缀补位,然后拼接,goto时还可省略%3,排序后分开时再加判断。
作者: batman    时间: 2009-11-20 00:16     标题: 本人的解

  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in (a.txt) do (
  3.     set /a hang+=1,lie=0
  4.     for %%b in (%%a) do (
  5.         set /a lie+=1&set "str=%%b"
  6.         if not defined fj if "!str:~,1!" equ "当" set /a fj=lie
  7.         if !hang! equ 1 (
  8.            if !lie! neq 1 set "_!lie!=%%b#:"
  9.            ) else (
  10.            if !lie! equ 1 (
  11.               set "ju=%%b"
  12.               ) else (
  13.               for %%c in (!lie!) do (
  14.                   if %%c lss !fj! (
  15.                      set /a num_%%c+=%%b
  16.                      if !str! equ 0 set "_%%c=!_%%c!!ju!,"
  17.                      ) else (
  18.                      if not defined %%c_%%b (
  19.                         set "%%c_%%b=!ju!%%b,"
  20.                         ) else (
  21.                         set "%%c_%%b=!%%c_%%b!!ju!%%b,"
  22.                      )
  23.                   )
  24.                )
  25.             )
  26.          )
  27.     )
  28. )
  29. cd.>b.txt
  30. for /l %%a in (2,1,%lie%) do (
  31.     set "str=!_%%a!"
  32.     if %%a lss %fj% (
  33.        for %%b in (!num_%%a!) do (
  34.            if "!str:~-1!" neq ":" (
  35.               set "str=!str:~,-1!"&echo !str:#=%%b,完成为0的局!>>b.txt
  36.               ) else (
  37.               echo !str:#=%%b,完成为0的局!无>>b.txt
  38.            )
  39.        )
  40.        ) else (
  41.        for /l %%b in (1,1,%hang%) do if defined %%a_%%b set "str=!str! !%%a_%%b!"
  42.        set "str=!str:#=!"&echo !str:~,-1!>>b.txt
  43.     )
  44. )
  45. start b.txt
复制代码


[ 本帖最后由 batman 于 2009-11-21 11:57 编辑 ]
作者: 523066680    时间: 2009-11-20 11:00

大概地模拟了一下2维数组,确实是一道“复合题”,后面的两行,我就不弄了
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set /a a=-1
  4. for /f "tokens=*" %%a in (a.x) do (
  5.    set /a a+=1,b=-1
  6.    for %%b in (%%a) do (
  7.       set /a b+=1
  8.       set str[!a!][!b!]=%%b
  9.    )
  10. )
  11. for /l %%b in (1,1,6) do (
  12.   for /l %%a in (1,1,%a%) do (
  13.     set /a !str[0][%%b]!+=str[%%a][%%b]
  14.     if "!str[%%a][%%b]!"=="0" (set zero%%b=!zero%%b!!str[%%a][0]!;)
  15.   )
  16.   if "!zero%%b!"=="" (set "zero%%b=无;")
  17.   for %%x in (!str[0][%%b]!) do (set now=!%%x!)
  18.   echo,!str[0][%%b]!!now! , 本次完成0的分局: !zero%%b:~0,-1!
  19. )
  20. pause
  21. exit
复制代码

作者: batman    时间: 2009-11-20 11:45     标题: 回复 23楼 的帖子

后面的两行才是本题的重点哦。。。
作者: 523066680    时间: 2009-11-20 12:05

如果要算法来排序,可能会选择用选择排序吧。。。。。。
排序可是个出过的题。你们用set 变量名, 用冒泡,用选择,用希尔,然后呢?
作者: zqz0012005    时间: 2009-11-20 12:17

看了一下,排序的问题和帖子有不少
http://www.bathome.net/viewthread.php?tid=1336
http://www.bathome.net/viewthread.php?tid=1581
http://www.bathome.net/viewthread.php?tid=4819
http://www.bathome.net/viewthread.php?tid=4196&page=1#pid26902

[ 本帖最后由 zqz0012005 于 2009-11-20 12:32 编辑 ]
作者: batman    时间: 2009-11-20 13:16     标题: 回复 26楼 的帖子

我现在用的方法可不是排序哦,严格上来讲应属于变量赋值法。
作者: zqz0012005    时间: 2009-11-20 13:24

所谓的“偏方”,其实也是良方
http://www.bathome.net/viewthread.php?tid=1581&page=1#pid8439

[ 本帖最后由 zqz0012005 于 2009-11-20 13:25 编辑 ]
作者: 523066680    时间: 2009-11-20 14:07

还是做了
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. ::第一部分是赋值二维数组模型
  4. set /a a=-1
  5. for /f "tokens=*" %%a in (a.x) do (
  6.    set /a a+=1,b=-1
  7.    for %%b in (%%a) do (
  8.       set /a b+=1
  9.       set str[!a!][!b!]=%%b
  10.    )
  11. )
  12. set /a 项目数=b-2
  13. ::给出某项任务完成的个数,并找出0的局
  14. for /l %%b in (1,1,%项目数%) do (
  15.   for /l %%a in (1,1,%a%) do (
  16.     set /a !str[0][%%b]!+=str[%%a][%%b]
  17.     if "!str[%%a][%%b]!"=="0" (set zero%%b=!zero%%b!!str[%%a][0]!;)
  18.   )
  19.   if "!zero%%b!"=="" (set "zero%%b=无;")
  20.   for %%x in (!str[0][%%b]!) do (set now=!%%x!)
  21.   echo,!str[0][%%b]!!now! , 本次完成0的分局: !zero%%b:~0,-1!
  22. )
  23. ::最后两列,和对应的项目名按顺序,匹配好并列出
  24. set /a last=b-1
  25. :result
  26. set result=!str[0][%last%]!:
  27. for /l %%b in (1,1,%a%) do (
  28.    for /l %%a in (1,1,%a%) do (
  29.      if "!str[%%a][%last%]!"=="%%b" (
  30.        set result=!result! !str[%%a][0]!!str[%%a][%last%]!
  31.      )
  32.    )
  33. )
  34. echo,%result%
  35. if %last% lss %b% (set /a last+=1 &goto :result)
  36. pause
  37. exit
复制代码

[ 本帖最后由 523066680 于 2009-11-20 14:49 编辑 ]
作者: batman    时间: 2009-11-20 14:50     标题: 回复 29楼 的帖子

针对此代码发表点个人意见,不当之处还请误解:
一、优点:
1、在批处理中引入数组概念,拓展了批的处理功能;
2、代码较简洁,这其实也是因为引入了数组,减少了累加赋值的过程;
3、书写较规范,但请注意a.x是不符合题意的。
二、不足之处:
1、因为代码是用数组变量表示的每个单元的值,所以变量用量较大,如达到百行百列时,变
量就要用到一万个,是对系统资源的考验;
2、出现6这个常量,这与题意中未知行未知列是不相符的;
3、代码中使用了goto循环,在效率上比for循环要低。
总之,exist这段代码还是表现出了其高水平的批处理技巧,值得大家学习。
作者: 523066680    时间: 2009-11-20 14:59

对出现的6进行了修补
数组赋值后遗留的 a b变量分别表示行和列
因为最后两列是排名,我用项目数=b-2表示项目数量,剔除了6

不足之处,表示同意。

[ 本帖最后由 523066680 于 2009-11-20 16:41 编辑 ]
作者: 523066680    时间: 2009-11-21 09:22     标题: 我也发表一点观点

事实上这道题会遇到的排序问题,根之前讨论的纯数字排序有一点不同
就是你要:给这个项目排序,不管你怎样操作,
          最终都必须为每个数字匹配这个数值的"主人"  并显示出来。

这个问题在表格操作中是经常会遇到的,例如给学生各科成绩排名
此时要排的就不仅仅是数值,还有该分值对应的"主人"   
针对于各列并且要关系到其中一项的行上其他数据时,我认为应该让批处理加入 二维数组 概念

[ 本帖最后由 523066680 于 2009-11-21 10:02 编辑 ]
作者: batman    时间: 2009-11-21 11:56

&&这个问题的确是我在工作中遇到和解决的,实际上的操作是用批先生成一个temp.vbs,

然后用temp.vbs读取指定工作表的指定分页(sheet*)的指定范围指定单元格的数据,然

后输入到temp.txt(这是用批做不到的),然后用批进行数据统计分析并输出最终想要的结

果。这是个实用性很强的问题,因为考虑难度比较大,所以在出题时省去了读取excel表数

据的步骤,直接给出了temp.txt的内容。所以请工作中与excel表打交道的会员都认真做一下

本题,不做也可以对照前面给出的代码仔细思考一下,说不定以后你就会遇到类似的问题。
作者: Seter    时间: 2009-11-21 19:36

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set/pt=<in.txt
  4. set t=!t:  = !
  5. set max1=0
  6. set max2=0
  7. for %%i in (%t:~2,-11%) do (
  8.    set/an+=1
  9.    set n!n!=%%i
  10. )
  11. for /f "skip=1 tokens=1* delims= " %%i in (in.txt) do (
  12.    set i=0
  13.    for %%z in (%%j) do (
  14.       set/ai+=1
  15.       if !i! leq %n% (
  16.          for %%y in (!i!) do (
  17.             if %%z==0 (
  18.                for %%x in (w!n%%y!) do (
  19.                   set %%x=!%%x!,%%i
  20.                )
  21.             ) else (
  22.                set/as!n%%y!+=%%z
  23.             )
  24.          )
  25.       ) else (
  26.          if defined p (
  27.             set p=
  28.             set y%%z=!y%%z!,%%i%%z
  29.             if !max2! lss %%z (
  30.                set max2=%%z
  31.             )
  32.          ) else (
  33.             set p=1
  34.             set r%%z=!r%%z!,%%i%%z
  35.             if !max1! lss %%z (
  36.                set max1=%%z
  37.             )
  38.          )
  39.       )
  40.    )
  41. )
  42. for /l %%i in (1,1,%n%) do (
  43.    set o=!n%%i!
  44.    for %%x in (s!n%%i!) do (
  45.       set o=!o!!%%x!,完成为0的局:
  46.       if defined w!n%%i! (
  47.          for %%x in (w!n%%i!) do (
  48.             echo !o!!%%x:~1!
  49.          )
  50.       ) else (
  51.          echo !o!无
  52.       )
  53.    )
  54. )
  55. set o=
  56. for /l %%i in (1,1,%max1%) do (
  57.    set o=!o!!r%%i!
  58. )
  59. echo 当日排名:!o:~1!
  60. set o=
  61. for /l %%i in (1,1,%max2%) do (
  62.    set o=!o!!y%%i!
  63. )
  64. echo 当月累计排名:!o:~1!
  65. pause>nul
复制代码

[ 本帖最后由 Seter 于 2009-11-21 21:42 编辑 ]
作者: batman    时间: 2009-11-21 20:51     标题: 回复 34楼 的帖子

输出时当日排名和当月排名搞反了!
作者: Seter    时间: 2009-11-21 21:43

回楼上的
修改好了...我发现问题在于用于辨别的变量p被我设定为环境变量了,所以我调试的时候if defined p是通过的,结果我就把对的改错了..
作者: Seter    时间: 2009-11-22 10:15

什么?连标题中的"部门 当天排名 当月累计排名"都是不确定的!?
作者: more    时间: 2009-11-24 16:28

还是让合适的工具来做最适合的工作吧,以前我先用bat来处理数据,发现效率太低了,后来又用bat调用vbs处理,感觉没那么顺手,接触到vba后,哈哈,有了相见恨晚的感觉...
我想,可能batman还不知道excel里有一个叫做vba(快捷键为Alt+F8)的东西吧,用VBE(快捷键Alt+F11)编写的,用下面的代码(vba)就高效多了,哈哈...
  1. Option Explicit
  2. Sub JustDoIt()
  3.   Dim AllColumns As Integer, AllRows As Integer, i As Integer, j As Integer, ADuty As Integer, Info As String, _
  4.     Info2 As String
  5.   AllColumns = Range("iv1").End(xlToLeft).Column       '获取数据区列数
  6.   AllRows = Range("a65536").End(xlUp).Row              '获取数据区行数
  7.   For i = 2 To AllColumns - 2
  8.     Info = ""
  9.     ADuty = 0
  10.     For j = 2 To AllRows
  11.       If Cells(j, i) > 0 Then
  12.         ADuty = ADuty + Cells(j, i)
  13.       Else
  14.         Info = Info & Cells(j, 1) & ","
  15.       End If
  16.     Next
  17.     If Info = "" Then Info = "无"
  18.     Cells(i, AllColumns + 1) = Cells(1, i) & ADuty & ", 完成为 0 的局: " & Info
  19.   Next
  20.   Info = "当日排名: "
  21.   Info2 = "当月累计排名: "
  22.   For i = 1 To AllRows
  23.     For j = 2 To AllRows
  24.       If Cells(j, AllColumns - 1) = i Then Info = Info & Cells(j, 1) & i & ","
  25.       If Cells(j, AllColumns) = i Then Info2 = Info2 & Cells(j, 1) & i & ","
  26.     Next
  27.   Next
  28.   Cells(AllColumns, AllColumns + 1) = Info & vbCrLf & Info2
  29.   Columns(AllColumns + 1).AutoFit
  30.   Cells(AllColumns, AllColumns + 1).Select
  31. End Sub
复制代码

作者: batman    时间: 2009-11-24 16:40     标题: 回复 38楼 的帖子

vba我怎么会不知道啊,呵呵,最简单的不是你这样的,而是用excel的函数来解决。
作者: more    时间: 2009-11-24 16:52

函数完成不了1楼要求的显示效果吧,而在33楼你却说实际工作中是用vbs来操作的嘛...还生成一个b.txt...
作者: zqz0012005    时间: 2009-11-24 19:07     标题: 回复 40楼 的帖子

vbs可以调用excel,同时还可以让这个excel执行VBA,并调用其中的函数。
所以说vbs是强大滴。




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2